forked from enlightenment/efl
Evas: 3D: Introducing 3D scene rendering features
Enable 3D features using --enable-evas-3d=yes when configuring. APIs are exposed through Evas_3D.h. Currently, evas-3d is being supported only on gl_x11 engine. Conflicts: src/lib/evas/Evas_Eo.h
This commit is contained in:
parent
96f9353f4c
commit
8fda631730
17
configure.ac
17
configure.ac
|
@ -1811,6 +1811,22 @@ AC_DEFINE_IF([EVAS_CSERVE2],
|
|||
[1], [Shared cache server.])
|
||||
AM_CONDITIONAL([EVAS_CSERVE2], [test "x${want_evas_cserve2}" = "xyes"])
|
||||
|
||||
# Evas 3D
|
||||
AC_ARG_ENABLE([evas-3d],
|
||||
[AC_HELP_STRING([--enable-evas-3d],
|
||||
[enable 3D scene graph features on evas. @<:default=disabled@:>@])],
|
||||
[
|
||||
if test "x${enableval}" = "xyes" ; then
|
||||
want_evas_3d="yes"
|
||||
else
|
||||
want_evas_3d="no"
|
||||
fi
|
||||
],
|
||||
[want_evas_3d="no"])
|
||||
|
||||
AC_DEFINE_IF([EVAS_3D], [test "x${want_evas_3d}" = "xyes"], [1], [3D scene graph rendering.])
|
||||
AM_CONDITIONAL([EVAS_3D], [test "x${want_evas_3d}" = "xyes"])
|
||||
|
||||
### Configuration
|
||||
|
||||
## Tile rotation
|
||||
|
@ -1852,6 +1868,7 @@ EFL_ADD_FEATURE([EVAS], [harfbuzz])
|
|||
EFL_ADD_FEATURE([EVAS], [cserve], [${want_evas_cserve2}])
|
||||
EFL_ADD_FEATURE([EVAS], [tile-rotate])
|
||||
EFL_ADD_FEATURE([EVAS], [dither-mask], [${build_evas_dither_mask}])
|
||||
EFL_ADD_FEATURE([EVAS], [evas-3d], [${want_evas_3d}])
|
||||
|
||||
EFL_LIB_END([Evas])
|
||||
#### End of Evas
|
||||
|
|
|
@ -251,6 +251,24 @@ lib/evas/file/evas_path.h
|
|||
lib_evas_libevas_la_SOURCES += \
|
||||
$(lib_evas_file_SOURCES)
|
||||
|
||||
# 3D
|
||||
dist_installed_evasmainheaders_DATA += lib/evas/Evas_3D.h
|
||||
|
||||
noinst_HEADERS += \
|
||||
lib/evas/include/evas_3d_utils.h \
|
||||
lib/evas/include/evas_3d_private.h
|
||||
|
||||
lib_evas_libevas_la_SOURCES += \
|
||||
lib/evas/canvas/evas_3d_object.c \
|
||||
lib/evas/canvas/evas_3d_scene.c \
|
||||
lib/evas/canvas/evas_3d_node.c \
|
||||
lib/evas/canvas/evas_3d_camera.c \
|
||||
lib/evas/canvas/evas_3d_light.c \
|
||||
lib/evas/canvas/evas_3d_mesh.c \
|
||||
lib/evas/canvas/evas_3d_texture.c \
|
||||
lib/evas/canvas/evas_3d_material.c \
|
||||
lib/evas/canvas/evas_3d_mesh_loader_md2.c
|
||||
|
||||
# Engine
|
||||
lib_evas_libevas_la_SOURCES += \
|
||||
lib/evas/common/evas_op_copy_main_.c \
|
||||
|
@ -713,6 +731,14 @@ modules/evas/engines/gl_common/shader/yuy2_nomul_frag.h \
|
|||
modules/evas/engines/gl_common/shader/yuy2_nomul_vert.h \
|
||||
modules/evas/engines/gl_common/shader/yuy2_vert.h
|
||||
|
||||
# 3D
|
||||
GL_COMMON_SOURCES += \
|
||||
modules/evas/engines/gl_common/evas_gl_3d_common.h \
|
||||
modules/evas/engines/gl_common/evas_gl_3d_private.h \
|
||||
modules/evas/engines/gl_common/evas_gl_3d.c \
|
||||
modules/evas/engines/gl_common/evas_gl_3d_renderer.c \
|
||||
modules/evas/engines/gl_common/evas_gl_3d_shader.c
|
||||
|
||||
EXTRA_DIST += \
|
||||
modules/evas/engines/gl_common/shader/compile.sh \
|
||||
modules/evas/engines/gl_common/shader/make-c-str.sh \
|
||||
|
|
|
@ -292,7 +292,6 @@ extern "C" {
|
|||
#ifdef EFL_EO_API_SUPPORT
|
||||
#include <Evas_Eo.h>
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,289 @@
|
|||
#ifndef _EVAS_3D_H
|
||||
#define _EVAS_3D_H
|
||||
|
||||
#include <Evas.h>
|
||||
|
||||
typedef float Evas_Real;
|
||||
|
||||
typedef struct _Evas_3D_Scene Evas_3D_Scene;
|
||||
typedef struct _Evas_3D_Node Evas_3D_Node;
|
||||
typedef struct _Evas_3D_Camera Evas_3D_Camera;
|
||||
typedef struct _Evas_3D_Light Evas_3D_Light;
|
||||
typedef struct _Evas_3D_Mesh Evas_3D_Mesh;
|
||||
typedef struct _Evas_3D_Texture Evas_3D_Texture;
|
||||
typedef struct _Evas_3D_Material Evas_3D_Material;
|
||||
|
||||
typedef enum _Evas_3D_Space
|
||||
{
|
||||
EVAS_3D_SPACE_LOCAL,
|
||||
EVAS_3D_SPACE_PARENT,
|
||||
EVAS_3D_SPACE_WORLD,
|
||||
} Evas_3D_Space;
|
||||
|
||||
typedef enum _Evas_3D_Node_Type
|
||||
{
|
||||
EVAS_3D_NODE_TYPE_NODE,
|
||||
EVAS_3D_NODE_TYPE_CAMERA,
|
||||
EVAS_3D_NODE_TYPE_LIGHT,
|
||||
EVAS_3D_NODE_TYPE_MESH,
|
||||
} Evas_3D_Node_Type;
|
||||
|
||||
typedef enum _Evas_3D_Vertex_Attrib
|
||||
{
|
||||
EVAS_3D_VERTEX_POSITION,
|
||||
EVAS_3D_VERTEX_NORMAL,
|
||||
EVAS_3D_VERTEX_TANGENT,
|
||||
EVAS_3D_VERTEX_COLOR,
|
||||
EVAS_3D_VERTEX_TEXCOORD,
|
||||
} Evas_3D_Vertex_Attrib;
|
||||
|
||||
typedef enum _Evas_3D_Index_Format
|
||||
{
|
||||
EVAS_3D_INDEX_FORMAT_NONE,
|
||||
EVAS_3D_INDEX_FORMAT_UNSIGNED_BYTE,
|
||||
EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT,
|
||||
} Evas_3D_Index_Format;
|
||||
|
||||
typedef enum _Evas_3D_Vertex_Assembly
|
||||
{
|
||||
EVAS_3D_VERTEX_ASSEMBLY_POINTS,
|
||||
EVAS_3D_VERTEX_ASSEMBLY_LINES,
|
||||
EVAS_3D_VERTEX_ASSEMBLY_LINE_STRIP,
|
||||
EVAS_3D_VERTEX_ASSEMBLY_LINE_LOOP,
|
||||
EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES,
|
||||
EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_STRIP,
|
||||
EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_FAN,
|
||||
} Evas_3D_Vertex_Assembly;
|
||||
|
||||
typedef enum _Evas_3D_Color_Format
|
||||
{
|
||||
EVAS_3D_COLOR_FORMAT_RGBA,
|
||||
EVAS_3D_COLOR_FORMAT_RGB,
|
||||
EVAS_3D_COLOR_FORMAT_ALPHA,
|
||||
} Evas_3D_Color_Format;
|
||||
|
||||
typedef enum _Evas_3D_Pixel_Format
|
||||
{
|
||||
EVAS_3D_PIXEL_FORMAT_8,
|
||||
EVAS_3D_PIXEL_FORMAT_565,
|
||||
EVAS_3D_PIXEL_FORMAT_888,
|
||||
EVAS_3D_PIXEL_FORMAT_8888,
|
||||
EVAS_3D_PIXEL_FORMAT_4444,
|
||||
EVAS_3D_PIXEL_FORMAT_5551,
|
||||
} Evas_3D_Pixel_Format;
|
||||
|
||||
typedef enum _Evas_3D_Wrap_Mode
|
||||
{
|
||||
EVAS_3D_WRAP_MODE_CLAMP,
|
||||
EVAS_3D_WRAP_MODE_REPEAT,
|
||||
EVAS_3D_WRAP_MODE_REFLECT,
|
||||
} Evas_3D_Wrap_Mode;
|
||||
|
||||
typedef enum _Evas_3D_Texture_Filter
|
||||
{
|
||||
EVAS_3D_TEXTURE_FILTER_NEAREST,
|
||||
EVAS_3D_TEXTURE_FILTER_LINEAR,
|
||||
EVAS_3D_TEXTURE_FILTER_NEAREST_MIPMAP_NEAREST,
|
||||
EVAS_3D_TEXTURE_FILTER_LINEAR_MIPMAP_NEAREST,
|
||||
EVAS_3D_TEXTURE_FILTER_NEAREST_MIPMAP_LINEAR,
|
||||
EVAS_3D_TEXTURE_FILTER_LINEAR_MIPMAP_LINEAR,
|
||||
} Evas_3D_Texture_Filter;
|
||||
|
||||
typedef enum _Evas_3D_Shade_Mode
|
||||
{
|
||||
EVAS_3D_SHADE_MODE_VERTEX_COLOR,
|
||||
EVAS_3D_SHADE_MODE_DIFFUSE,
|
||||
EVAS_3D_SHADE_MODE_FLAT,
|
||||
EVAS_3D_SHADE_MODE_PHONG,
|
||||
EVAS_3D_SHADE_MODE_NORMAL_MAP,
|
||||
} Evas_3D_Shade_Mode;
|
||||
|
||||
typedef enum _Evas_3D_Material_Attrib
|
||||
{
|
||||
EVAS_3D_MATERIAL_AMBIENT,
|
||||
EVAS_3D_MATERIAL_DIFFUSE,
|
||||
EVAS_3D_MATERIAL_SPECULAR,
|
||||
EVAS_3D_MATERIAL_EMISSION,
|
||||
EVAS_3D_MATERIAL_NORMAL,
|
||||
} Evas_3D_Material_Attrib;
|
||||
|
||||
typedef enum _Evas_3D_Mesh_File_Type
|
||||
{
|
||||
EVAS_3D_MESH_FILE_TYPE_MD2,
|
||||
} Evas_3D_Mesh_File_Type;
|
||||
|
||||
typedef enum _Evas_3D_Pick_Type
|
||||
{
|
||||
EVAS_3D_PICK_NODE,
|
||||
EVAS_3D_PICK_MESH,
|
||||
} Evas_3D_Pick_Type;
|
||||
|
||||
/* Image object render target */
|
||||
EAPI void evas_object_image_3d_scene_set(Evas_Object *obj, Evas_3D_Scene *scene) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Scene *evas_object_image_3d_scene_get(const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
/* Scene */
|
||||
EAPI Evas_3D_Scene *evas_3d_scene_add(Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_scene_del(Evas_3D_Scene *scene) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas *evas_3d_scene_evas_get(const Evas_3D_Scene *scene) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_scene_root_node_set(Evas_3D_Scene *scene, Evas_3D_Node *node) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Node *evas_3d_scene_root_node_get(const Evas_3D_Scene *scene) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_scene_camera_node_set(Evas_3D_Scene *scene, Evas_3D_Node *node) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Node *evas_3d_scene_camera_node_get(const Evas_3D_Scene *scene) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_scene_size_set(Evas_3D_Scene *scene, int w, int h) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_scene_size_get(const Evas_3D_Scene *scene, int *w, int *h) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_scene_background_color_set(Evas_3D_Scene *scene, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_scene_background_color_get(const Evas_3D_Scene *scene, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI Eina_Bool evas_3d_scene_pick(const Evas_3D_Scene *scene, Evas_Real x, Evas_Real y, Evas_3D_Node **node, Evas_3D_Mesh **mesh, Evas_Real *s, Evas_Real *t) EINA_ARG_NONNULL(1);
|
||||
|
||||
/* Node */
|
||||
EAPI Evas_3D_Node *evas_3d_node_add(Evas *e, Evas_3D_Node_Type type) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_del(Evas_3D_Node *node) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Node_Type evas_3d_node_type_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI Evas *evas_3d_node_evas_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_member_add(Evas_3D_Node *node, Evas_3D_Node *member) EINA_ARG_NONNULL(1, 2);
|
||||
EAPI void evas_3d_node_member_del(Evas_3D_Node *node, Evas_3D_Node *member) EINA_ARG_NONNULL(1, 2);
|
||||
EAPI Evas_3D_Node *evas_3d_node_parent_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI const Eina_List *evas_3d_node_member_list_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_position_set(Evas_3D_Node *node, Evas_Real x, Evas_Real y, Evas_Real z) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_orientation_set(Evas_3D_Node *node, Evas_Real x, Evas_Real y, Evas_Real z, Evas_Real w) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_orientation_euler_set(Evas_3D_Node *node, Evas_Real x, Evas_Real y, Evas_Real z) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_orientation_angle_axis_set(Evas_3D_Node *node, Evas_Real angle, Evas_Real x, Evas_Real y, Evas_Real z) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_scale_set(Evas_3D_Node *node, Evas_Real x, Evas_Real y, Evas_Real z) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_position_get(const Evas_3D_Node *node, Evas_3D_Space space, Evas_Real *x, Evas_Real *y, Evas_Real *z) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_orientation_get(const Evas_3D_Node *node, Evas_3D_Space space, Evas_Real *x, Evas_Real *y, Evas_Real *z, Evas_Real *w) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_scale_get(const Evas_3D_Node *node, Evas_3D_Space space, Evas_Real *x, Evas_Real *y, Evas_Real *z) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_position_inherit_set(Evas_3D_Node *node, Eina_Bool inherit) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_orientation_inherit_set(Evas_3D_Node *node, Eina_Bool inherit) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_scale_inherit_set(Evas_3D_Node *node, Eina_Bool inherit) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI Eina_Bool evas_3d_node_position_inherit_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI Eina_Bool evas_3d_node_orientation_inherit_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI Eina_Bool evas_3d_node_scale_inherit_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_look_at_set(Evas_3D_Node *node, Evas_3D_Space target_space, Evas_Real x, Evas_Real y, Evas_Real z, Evas_3D_Space up_space, Evas_Real ux, Evas_Real uy, Evas_Real uz) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_camera_set(Evas_3D_Node *node, Evas_3D_Camera *camera) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Camera *evas_3d_node_camera_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_light_set(Evas_3D_Node *node, Evas_3D_Light *light) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Light *evas_3d_node_light_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_node_mesh_add(Evas_3D_Node *node, Evas_3D_Mesh *mesh) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_mesh_del(Evas_3D_Node *node, Evas_3D_Mesh *mesh) EINA_ARG_NONNULL(1);
|
||||
EAPI const Eina_List *evas_3d_node_mesh_list_get(const Evas_3D_Node *node) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_node_mesh_frame_set(Evas_3D_Node *node, Evas_3D_Mesh *mesh, int frame) EINA_ARG_NONNULL(1);
|
||||
EAPI int evas_3d_node_mesh_frame_get(const Evas_3D_Node *node, Evas_3D_Mesh *mesh) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
/* Camera */
|
||||
EAPI Evas_3D_Camera *evas_3d_camera_add(Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_camera_del(Evas_3D_Camera *camera) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas *evas_3d_camera_evas_get(const Evas_3D_Camera *camera) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_camera_projection_matrix_set(Evas_3D_Camera *camera, const Evas_Real *matrix) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_camera_projection_matrix_get(const Evas_3D_Camera *camera, Evas_Real *matrix) EINA_ARG_NONNULL(1, 2);
|
||||
EAPI void evas_3d_camera_projection_perspective_set(Evas_3D_Camera *camera, Evas_Real fovy, Evas_Real aspect, Evas_Real near, Evas_Real far) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_camera_projection_frustum_set(Evas_3D_Camera *camera, Evas_Real left, Evas_Real right, Evas_Real bottom, Evas_Real top, Evas_Real near, Evas_Real far) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_camera_projection_ortho_set(Evas_3D_Camera *camera, Evas_Real left, Evas_Real right, Evas_Real bottom, Evas_Real top, Evas_Real near, Evas_Real far) EINA_ARG_NONNULL(1);
|
||||
|
||||
/* Light */
|
||||
EAPI Evas_3D_Light *evas_3d_light_add(Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_del(Evas_3D_Light *light) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas *evas_3d_light_evas_get(const Evas_3D_Light *light) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_light_directional_set(Evas_3D_Light *light, Eina_Bool directional) EINA_ARG_NONNULL(1);
|
||||
EAPI Eina_Bool evas_3d_light_directional_get(const Evas_3D_Light *light) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_light_ambient_set(Evas_3D_Light *light, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_ambient_get(const Evas_3D_Light *light, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_diffuse_set(Evas_3D_Light *light, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_diffuse_get(const Evas_3D_Light *light, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_specular_set(Evas_3D_Light *light, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_specular_get(const Evas_3D_Light *light, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_spot_exponent_set(Evas_3D_Light *light, Evas_Real exponent) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_Real evas_3d_light_spot_exponent_get(const Evas_3D_Light *light) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_spot_cutoff_set(Evas_3D_Light *light, Evas_Real cutoff) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_Real evas_3d_light_spot_cutoff_get(const Evas_3D_Light *light) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_attenuation_set(Evas_3D_Light *light, Evas_Real constant, Evas_Real linear, Evas_Real quadratic) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_light_attenuation_get(const Evas_3D_Light *light, Evas_Real *constant, Evas_Real *linear, Evas_Real *quadratic) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_light_attenuation_enable_set(Evas_3D_Light *light, Eina_Bool enable) EINA_ARG_NONNULL(1);
|
||||
EAPI Eina_Bool evas_3d_light_attenuation_enable_get(const Evas_3D_Light *light) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
/* Mesh */
|
||||
EAPI Evas_3D_Mesh *evas_3d_mesh_add(Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_mesh_del(Evas_3D_Mesh *mesh) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas *evas_3d_mesh_evas_get(const Evas_3D_Mesh *mesh) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_shade_mode_set(Evas_3D_Mesh *mesh, Evas_3D_Shade_Mode mode) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Shade_Mode evas_3d_mesh_shade_mode_get(const Evas_3D_Mesh *mesh) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_file_set(Evas_3D_Mesh *mesh, Evas_3D_Mesh_File_Type type, const char *file, const char *key) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_vertex_count_set(Evas_3D_Mesh *mesh, unsigned int count) EINA_ARG_NONNULL(1);
|
||||
EAPI int evas_3d_mesh_vertex_count_get(const Evas_3D_Mesh *mesh) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_frame_add(Evas_3D_Mesh *mesh, int frame) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_mesh_frame_del(Evas_3D_Mesh *mesh, int frame) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_frame_material_set(Evas_3D_Mesh *mesh, int frame, Evas_3D_Material *material) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Material *evas_3d_mesh_frame_material_get(const Evas_3D_Mesh *mesh, int frame) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_frame_vertex_data_set(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib, int stride, const void *data) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_mesh_frame_vertex_data_copy_set(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib, int stride, const void *data) EINA_ARG_NONNULL(1);
|
||||
EAPI void *evas_3d_mesh_frame_vertex_data_map(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_mesh_frame_vertex_data_unmap(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib) EINA_ARG_NONNULL(1);
|
||||
EAPI int evas_3d_mesh_frame_vertex_stride_get(const Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_index_data_set(Evas_3D_Mesh *mesh, Evas_3D_Index_Format format, int count, const void *indices) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_mesh_index_data_copy_set(Evas_3D_Mesh *mesh, Evas_3D_Index_Format format, int count, const void *indices) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Index_Format evas_3d_mesh_index_format_get(const Evas_3D_Mesh *mesh) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI int evas_3d_mesh_index_count_get(const Evas_3D_Mesh *mesh) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void *evas_3d_mesh_index_data_map(Evas_3D_Mesh *mesh) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_mesh_index_data_unmap(Evas_3D_Mesh *mesh) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_mesh_vertex_assembly_set(Evas_3D_Mesh *mesh, Evas_3D_Vertex_Assembly assembly);
|
||||
EAPI Evas_3D_Vertex_Assembly evas_3d_mesh_vertex_assembly_get(const Evas_3D_Mesh *mesh);
|
||||
|
||||
/* Texture */
|
||||
EAPI Evas_3D_Texture *evas_3d_texture_add(Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_texture_del(Evas_3D_Texture *texture) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas *evas_3d_texture_evas_get(const Evas_3D_Texture *texture) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_texture_data_set(Evas_3D_Texture *texture, Evas_3D_Color_Format color_format, Evas_3D_Pixel_Format pixel_format, int w, int h, const void *data);
|
||||
EAPI void evas_3d_texture_file_set(Evas_3D_Texture *texture, const char *file, const char *key) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_texture_source_set(Evas_3D_Texture *texture, Evas_Object *source) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Color_Format evas_3d_texture_color_format_get(const Evas_3D_Texture *texture) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_texture_size_get(const Evas_3D_Texture *texture, int *w, int *h) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_texture_wrap_set(Evas_3D_Texture *texture, Evas_3D_Wrap_Mode s, Evas_3D_Wrap_Mode t) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_texture_wrap_get(const Evas_3D_Texture *texture, Evas_3D_Wrap_Mode *s, Evas_3D_Wrap_Mode *t) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_texture_filter_set(Evas_3D_Texture *texture, Evas_3D_Texture_Filter min, Evas_3D_Texture_Filter mag) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_texture_filter_get(const Evas_3D_Texture *texture, Evas_3D_Texture_Filter *min, Evas_3D_Texture_Filter *mag) EINA_ARG_NONNULL(1);
|
||||
|
||||
/* Material */
|
||||
EAPI Evas_3D_Material *evas_3d_material_add(Evas *e) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_material_del(Evas_3D_Material *material) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas *evas_3d_material_evas_get(const Evas_3D_Material *material) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_material_enable_set(Evas_3D_Material *material, Evas_3D_Material_Attrib attrib, Eina_Bool enable) EINA_ARG_NONNULL(1);
|
||||
EAPI Eina_Bool evas_3d_material_enable_get(const Evas_3D_Material *material, Evas_3D_Material_Attrib attrib) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_material_color_set(Evas_3D_Material *material, Evas_3D_Material_Attrib attrib, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a) EINA_ARG_NONNULL(1);
|
||||
EAPI void evas_3d_material_color_get(const Evas_3D_Material *material, Evas_3D_Material_Attrib attrib, Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a) EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_material_shininess_set(Evas_3D_Material *material, Evas_Real shininess) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_Real evas_3d_material_shininess_get(const Evas_3D_Material *material) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
EAPI void evas_3d_material_texture_set(Evas_3D_Material *material, Evas_3D_Material_Attrib attrib, Evas_3D_Texture *texture) EINA_ARG_NONNULL(1);
|
||||
EAPI Evas_3D_Texture *evas_3d_material_texture_get(const Evas_3D_Material *material, Evas_3D_Material_Attrib attrib) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1);
|
||||
|
||||
#endif /* _EVAS_3D_H */
|
|
@ -0,0 +1,159 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
static void
|
||||
_camera_free(Evas_3D_Object *obj)
|
||||
{
|
||||
Evas_3D_Camera *camera = (Evas_3D_Camera *)obj;
|
||||
|
||||
if (camera->nodes)
|
||||
eina_hash_free(camera->nodes);
|
||||
|
||||
free(camera);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_camera_node_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
|
||||
void *data EINA_UNUSED, void *fdata)
|
||||
{
|
||||
Evas_3D_Node *n = *(Evas_3D_Node **)key;
|
||||
evas_3d_object_change(&n->base, EVAS_3D_STATE_NODE_CAMERA, (Evas_3D_Object *)fdata);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_camera_change(Evas_3D_Object *obj, Evas_3D_State state EINA_UNUSED,
|
||||
Evas_3D_Object *ref EINA_UNUSED)
|
||||
{
|
||||
Evas_3D_Camera *camera = (Evas_3D_Camera *)obj;
|
||||
|
||||
if (camera->nodes)
|
||||
eina_hash_foreach(camera->nodes, _camera_node_change_notify, obj);
|
||||
}
|
||||
|
||||
static const Evas_3D_Object_Func camera_func =
|
||||
{
|
||||
_camera_free,
|
||||
_camera_change,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void
|
||||
evas_3d_camera_node_add(Evas_3D_Camera *camera, Evas_3D_Node *node)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (camera->nodes == NULL)
|
||||
{
|
||||
camera->nodes = eina_hash_pointer_new(NULL);
|
||||
|
||||
if (camera->nodes == NULL)
|
||||
{
|
||||
ERR("Failed to create hash table.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
count = (int)eina_hash_find(camera->nodes, &node);
|
||||
|
||||
eina_hash_set(camera->nodes, &node, (const void *)(count + 1));
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_camera_node_del(Evas_3D_Camera *camera, Evas_3D_Node *node)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (camera->nodes == NULL)
|
||||
{
|
||||
ERR("No node to delete.");
|
||||
return;
|
||||
}
|
||||
|
||||
count = (int)eina_hash_find(camera->nodes, &node);
|
||||
|
||||
if (count == 1)
|
||||
eina_hash_del(camera->nodes, &node, NULL);
|
||||
else
|
||||
eina_hash_set(camera->nodes, &node, (const void *)(count - 1));
|
||||
}
|
||||
|
||||
Evas_3D_Camera *
|
||||
evas_3d_camera_new(Evas *e)
|
||||
{
|
||||
Evas_3D_Camera *camera = NULL;
|
||||
|
||||
camera = (Evas_3D_Camera *)calloc(1, sizeof(Evas_3D_Camera));
|
||||
|
||||
if (camera == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evas_3d_object_init(&camera->base, e, EVAS_3D_OBJECT_TYPE_CAMERA, &camera_func);
|
||||
return camera;
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Camera *
|
||||
evas_3d_camera_add(Evas *e)
|
||||
{
|
||||
return evas_3d_camera_new(e);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_camera_del(Evas_3D_Camera *camera)
|
||||
{
|
||||
evas_3d_object_unreference(&camera->base);
|
||||
}
|
||||
|
||||
EAPI Evas *
|
||||
evas_3d_camera_evas_get(const Evas_3D_Camera *camera)
|
||||
{
|
||||
return camera->base.evas;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_camera_projection_matrix_set(Evas_3D_Camera *camera, const Evas_Real *matrix)
|
||||
{
|
||||
evas_mat4_array_set(&camera->projection, matrix);
|
||||
evas_3d_object_change(&camera->base, EVAS_3D_STATE_CAMERA_PROJECTION, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_camera_projection_matrix_get(const Evas_3D_Camera *camera, Evas_Real *matrix)
|
||||
{
|
||||
memcpy(matrix, &camera->projection.m[0], sizeof(Evas_Real) * 16);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_camera_projection_perspective_set(Evas_3D_Camera *camera, Evas_Real fovy, Evas_Real aspect, Evas_Real near, Evas_Real far)
|
||||
{
|
||||
Evas_Real xmax;
|
||||
Evas_Real ymax;
|
||||
|
||||
ymax = near * (Evas_Real)tan((double)fovy * M_PI / 360.0);
|
||||
xmax = ymax * aspect;
|
||||
|
||||
evas_mat4_frustum_set(&camera->projection, -xmax, xmax, -ymax, ymax, near, far);
|
||||
evas_3d_object_change(&camera->base, EVAS_3D_STATE_CAMERA_PROJECTION, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_camera_projection_frustum_set(Evas_3D_Camera *camera, Evas_Real left, Evas_Real right, Evas_Real bottom, Evas_Real top, Evas_Real near, Evas_Real far)
|
||||
{
|
||||
evas_mat4_frustum_set(&camera->projection, left, right, bottom, top, near, far);
|
||||
evas_3d_object_change(&camera->base, EVAS_3D_STATE_CAMERA_PROJECTION, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_camera_projection_ortho_set(Evas_3D_Camera *camera, Evas_Real left, Evas_Real right, Evas_Real bottom, Evas_Real top, Evas_Real near, Evas_Real far)
|
||||
{
|
||||
evas_mat4_ortho_set(&camera->projection, left, right, bottom, top, near, far);
|
||||
evas_3d_object_change(&camera->base, EVAS_3D_STATE_CAMERA_PROJECTION, NULL);
|
||||
}
|
|
@ -0,0 +1,273 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
static void
|
||||
_light_free(Evas_3D_Object *obj)
|
||||
{
|
||||
Evas_3D_Light *light = (Evas_3D_Light *)obj;
|
||||
|
||||
if (light->nodes)
|
||||
eina_hash_free(light->nodes);
|
||||
|
||||
free(light);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_light_node_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
|
||||
void *data EINA_UNUSED, void *fdata)
|
||||
{
|
||||
Evas_3D_Node *n = *(Evas_3D_Node **)key;
|
||||
evas_3d_object_change(&n->base, EVAS_3D_STATE_NODE_LIGHT, (Evas_3D_Object *)fdata);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_light_change(Evas_3D_Object *obj, Evas_3D_State state EINA_UNUSED,
|
||||
Evas_3D_Object *ref EINA_UNUSED)
|
||||
{
|
||||
Evas_3D_Light *light = (Evas_3D_Light *)obj;
|
||||
|
||||
if (light->nodes)
|
||||
eina_hash_foreach(light->nodes, _light_node_change_notify, obj);
|
||||
}
|
||||
|
||||
static const Evas_3D_Object_Func light_func =
|
||||
{
|
||||
_light_free,
|
||||
_light_change,
|
||||
NULL,
|
||||
};
|
||||
|
||||
void
|
||||
evas_3d_light_node_add(Evas_3D_Light *light, Evas_3D_Node *node)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (light->nodes == NULL)
|
||||
{
|
||||
light->nodes = eina_hash_pointer_new(NULL);
|
||||
|
||||
if (light->nodes == NULL)
|
||||
{
|
||||
ERR("Failed to create hash table.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
count = (int)eina_hash_find(light->nodes, &node);
|
||||
|
||||
eina_hash_set(light->nodes, &node, (const void *)(count + 1));
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_light_node_del(Evas_3D_Light *light, Evas_3D_Node *node)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (light->nodes == NULL)
|
||||
{
|
||||
ERR("No node to delete.");
|
||||
return;
|
||||
}
|
||||
|
||||
count = (int)eina_hash_find(light->nodes, &node);
|
||||
|
||||
if (count == 1)
|
||||
eina_hash_del(light->nodes, &node, NULL);
|
||||
else
|
||||
eina_hash_set(light->nodes, &node, (const void *)(count - 1));
|
||||
}
|
||||
|
||||
Evas_3D_Light *
|
||||
evas_3d_light_new(Evas *e)
|
||||
{
|
||||
Evas_3D_Light *light = NULL;
|
||||
|
||||
light = (Evas_3D_Light *)calloc(1, sizeof(Evas_3D_Light));
|
||||
|
||||
if (light == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evas_3d_object_init(&light->base, e, EVAS_3D_OBJECT_TYPE_LIGHT, &light_func);
|
||||
|
||||
evas_color_set(&light->ambient, 0.0, 0.0, 0.0, 1.0);
|
||||
evas_color_set(&light->diffuse, 1.0, 1.0, 1.0, 1.0);
|
||||
evas_color_set(&light->specular, 1.0, 1.0, 1.0, 1.0);
|
||||
|
||||
light->spot_exp = 0.0;
|
||||
light->spot_cutoff = 180.0;
|
||||
light->spot_cutoff_cos = -1.0;
|
||||
|
||||
light->atten_const = 1.0;
|
||||
light->atten_linear = 0.0;
|
||||
light->atten_quad = 0.0;
|
||||
|
||||
return light;
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Light *
|
||||
evas_3d_light_add(Evas *e)
|
||||
{
|
||||
return evas_3d_light_new(e);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_del(Evas_3D_Light *light)
|
||||
{
|
||||
evas_3d_object_unreference(&light->base);
|
||||
}
|
||||
|
||||
EAPI Evas *
|
||||
evas_3d_light_evas_get(const Evas_3D_Light *light)
|
||||
{
|
||||
return light->base.evas;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_directional_set(Evas_3D_Light *light, Eina_Bool directional)
|
||||
{
|
||||
if (light->directional != directional)
|
||||
{
|
||||
light->directional = directional;
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_ANY, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_3d_light_directional_get(const Evas_3D_Light *light)
|
||||
{
|
||||
return light->directional;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_ambient_set(Evas_3D_Light *light, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
|
||||
{
|
||||
light->ambient.r = r;
|
||||
light->ambient.g = g;
|
||||
light->ambient.b = b;
|
||||
light->ambient.a = a;
|
||||
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_LIGHT_AMBIENT, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_ambient_get(const Evas_3D_Light *light,
|
||||
Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
|
||||
{
|
||||
if (r) *r = light->ambient.r;
|
||||
if (g) *g = light->ambient.g;
|
||||
if (b) *b = light->ambient.b;
|
||||
if (a) *a = light->ambient.a;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_diffuse_set(Evas_3D_Light *light, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
|
||||
{
|
||||
light->diffuse.r = r;
|
||||
light->diffuse.g = g;
|
||||
light->diffuse.b = b;
|
||||
light->diffuse.a = a;
|
||||
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_LIGHT_DIFFUSE, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_diffuse_get(const Evas_3D_Light *light,
|
||||
Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
|
||||
{
|
||||
if (r) *r = light->diffuse.r;
|
||||
if (g) *g = light->diffuse.g;
|
||||
if (b) *b = light->diffuse.b;
|
||||
if (a) *a = light->diffuse.a;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_specular_set(Evas_3D_Light *light, Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
|
||||
{
|
||||
light->specular.r = r;
|
||||
light->specular.g = g;
|
||||
light->specular.b = b;
|
||||
light->specular.a = a;
|
||||
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_LIGHT_SPECULAR, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_specular_get(const Evas_3D_Light *light,
|
||||
Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
|
||||
{
|
||||
if (r) *r = light->specular.r;
|
||||
if (g) *g = light->specular.g;
|
||||
if (b) *b = light->specular.b;
|
||||
if (a) *a = light->specular.a;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_spot_exponent_set(Evas_3D_Light *light, Evas_Real exponent)
|
||||
{
|
||||
light->spot_exp = exponent;
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_LIGHT_SPOT_EXP, NULL);
|
||||
}
|
||||
|
||||
EAPI Evas_Real
|
||||
evas_3d_light_spot_exponent_get(const Evas_3D_Light *light)
|
||||
{
|
||||
return light->spot_exp;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_spot_cutoff_set(Evas_3D_Light *light, Evas_Real cutoff)
|
||||
{
|
||||
light->spot_cutoff = cutoff;
|
||||
light->spot_cutoff_cos = cos(cutoff * M_PI / 180.0);
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_LIGHT_SPOT_CUTOFF, NULL);
|
||||
}
|
||||
|
||||
EAPI Evas_Real
|
||||
evas_3d_light_spot_cutoff_get(const Evas_3D_Light *light)
|
||||
{
|
||||
return light->spot_cutoff;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_attenuation_set(Evas_3D_Light *light,
|
||||
Evas_Real constant, Evas_Real linear, Evas_Real quadratic)
|
||||
{
|
||||
light->atten_const = constant;
|
||||
light->atten_linear = linear;
|
||||
light->atten_quad = quadratic;
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_LIGHT_ATTENUATION, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_attenuation_get(const Evas_3D_Light *light, Evas_Real *constant, Evas_Real *linear, Evas_Real *quadratic)
|
||||
{
|
||||
if (constant) *constant = light->atten_const;
|
||||
if (linear) *linear = light->atten_linear;
|
||||
if (quadratic) *quadratic = light->atten_quad;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_light_attenuation_enable_set(Evas_3D_Light *light, Eina_Bool enable)
|
||||
{
|
||||
if (light->enable_attenuation != enable)
|
||||
{
|
||||
light->enable_attenuation = enable;
|
||||
evas_3d_object_change(&light->base, EVAS_3D_STATE_LIGHT_ATTENUATION, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_3d_light_attenuation_enable_get(const Evas_3D_Light *light)
|
||||
{
|
||||
return light->enable_attenuation;
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
static void
|
||||
_material_free(Evas_3D_Object *obj)
|
||||
{
|
||||
int i;
|
||||
Evas_3D_Material *material = (Evas_3D_Material *)obj;
|
||||
|
||||
if (material->meshes)
|
||||
eina_hash_free(material->meshes);
|
||||
|
||||
for (i = 0; i < EVAS_3D_MATERIAL_ATTRIB_COUNT; i++)
|
||||
{
|
||||
if (material->attribs[i].texture)
|
||||
{
|
||||
evas_3d_texture_material_del(material->attribs[i].texture, material);
|
||||
evas_3d_object_unreference(&material->attribs[i].texture->base);
|
||||
}
|
||||
}
|
||||
|
||||
free(material);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_material_mesh_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
|
||||
void *data EINA_UNUSED, void *fdata)
|
||||
{
|
||||
Evas_3D_Mesh *m = *(Evas_3D_Mesh **)key;
|
||||
evas_3d_object_change(&m->base, EVAS_3D_STATE_MESH_MATERIAL, (Evas_3D_Object *)fdata);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_material_change(Evas_3D_Object *obj, Evas_3D_State state EINA_UNUSED,
|
||||
Evas_3D_Object *ref EINA_UNUSED)
|
||||
{
|
||||
Evas_3D_Material *material = (Evas_3D_Material *)obj;
|
||||
|
||||
if (material->meshes)
|
||||
eina_hash_foreach(material->meshes, _material_mesh_change_notify, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
_material_update(Evas_3D_Object *obj)
|
||||
{
|
||||
int i;
|
||||
Evas_3D_Material *material = (Evas_3D_Material *)obj;
|
||||
|
||||
for (i = 0; i < EVAS_3D_MATERIAL_ATTRIB_COUNT; i++)
|
||||
{
|
||||
if (material->attribs[i].enable)
|
||||
{
|
||||
if (material->attribs[i].texture)
|
||||
evas_3d_object_update(&material->attribs[i].texture->base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static const Evas_3D_Object_Func material_func =
|
||||
{
|
||||
_material_free,
|
||||
_material_change,
|
||||
_material_update,
|
||||
};
|
||||
|
||||
void
|
||||
evas_3d_material_mesh_add(Evas_3D_Material *material, Evas_3D_Mesh *mesh)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (material->meshes == NULL)
|
||||
{
|
||||
material->meshes = eina_hash_pointer_new(NULL);
|
||||
|
||||
if (material->meshes == NULL)
|
||||
{
|
||||
ERR("Failed to create hash table.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
count = (int)eina_hash_find(material->meshes, &mesh);
|
||||
|
||||
eina_hash_set(material->meshes, &mesh, (const void *)(count + 1));
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_material_mesh_del(Evas_3D_Material *material, Evas_3D_Mesh *mesh)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (material->meshes == NULL)
|
||||
{
|
||||
ERR("No mesh to delete.");
|
||||
return;
|
||||
}
|
||||
|
||||
count = (int)eina_hash_find(material->meshes, &mesh);
|
||||
|
||||
if (count == 1)
|
||||
eina_hash_del(material->meshes, &mesh, NULL);
|
||||
else
|
||||
eina_hash_set(material->meshes, &mesh, (const void *)(count - 1));
|
||||
}
|
||||
|
||||
Evas_3D_Material *
|
||||
evas_3d_material_new(Evas *e)
|
||||
{
|
||||
Evas_3D_Material *material = NULL;
|
||||
|
||||
material = (Evas_3D_Material *)calloc(1, sizeof(Evas_3D_Material));
|
||||
|
||||
if (material == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evas_3d_object_init(&material->base, e, EVAS_3D_OBJECT_TYPE_MATERIAL, &material_func);
|
||||
|
||||
evas_color_set(&material->attribs[EVAS_3D_MATERIAL_AMBIENT].color, 0.2, 0.2, 0.2, 1.0);
|
||||
evas_color_set(&material->attribs[EVAS_3D_MATERIAL_DIFFUSE].color, 0.8, 0.8, 0.8, 1.0);
|
||||
evas_color_set(&material->attribs[EVAS_3D_MATERIAL_SPECULAR].color, 1.0, 1.0, 1.0, 1.0);
|
||||
evas_color_set(&material->attribs[EVAS_3D_MATERIAL_EMISSION].color, 0.0, 0.0, 0.0, 1.0);
|
||||
material->shininess = 150.0;
|
||||
|
||||
return material;
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Material *
|
||||
evas_3d_material_add(Evas *e)
|
||||
{
|
||||
return evas_3d_material_new(e);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_material_del(Evas_3D_Material *material)
|
||||
{
|
||||
evas_3d_object_unreference(&material->base);
|
||||
}
|
||||
|
||||
EAPI Evas *
|
||||
evas_3d_material_evas_get(const Evas_3D_Material *material)
|
||||
{
|
||||
return material->base.evas;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_material_enable_set(Evas_3D_Material *material, Evas_3D_Material_Attrib attrib,
|
||||
Eina_Bool enable)
|
||||
{
|
||||
material->attribs[attrib].enable = enable;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_3d_material_enable_get(const Evas_3D_Material *material, Evas_3D_Material_Attrib attrib)
|
||||
{
|
||||
return material->attribs[attrib].enable;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_material_color_set(Evas_3D_Material *material, Evas_3D_Material_Attrib attrib,
|
||||
Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
|
||||
{
|
||||
evas_color_set(&material->attribs[attrib].color, r, g, b, a);
|
||||
evas_3d_object_change(&material->base, EVAS_3D_STATE_MATERIAL_COLOR, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_material_color_get(const Evas_3D_Material *material, Evas_3D_Material_Attrib attrib,
|
||||
Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
|
||||
{
|
||||
if (r) *r = material->attribs[attrib].color.r;
|
||||
if (g) *g = material->attribs[attrib].color.g;
|
||||
if (b) *b = material->attribs[attrib].color.b;
|
||||
if (a) *a = material->attribs[attrib].color.a;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_material_shininess_set(Evas_3D_Material *material, Evas_Real shininess)
|
||||
{
|
||||
material->shininess = shininess;
|
||||
}
|
||||
|
||||
EAPI Evas_Real
|
||||
evas_3d_material_shininess_get(const Evas_3D_Material *material)
|
||||
{
|
||||
return material->shininess;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_material_texture_set(Evas_3D_Material *material, Evas_3D_Material_Attrib attrib,
|
||||
Evas_3D_Texture *texture)
|
||||
{
|
||||
if (material->attribs[attrib].texture != texture)
|
||||
{
|
||||
if (material->attribs[attrib].texture)
|
||||
{
|
||||
evas_3d_texture_material_del(material->attribs[attrib].texture, material);
|
||||
evas_3d_object_unreference(&material->attribs[attrib].texture->base);
|
||||
}
|
||||
|
||||
material->attribs[attrib].texture = texture;
|
||||
evas_3d_texture_material_add(texture, material);
|
||||
evas_3d_object_reference(&texture->base);
|
||||
}
|
||||
|
||||
evas_3d_object_change(&material->base, EVAS_3D_STATE_MATERIAL_TEXTURE, NULL);
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Texture *
|
||||
evas_3d_material_texture_get(const Evas_3D_Material *material, Evas_3D_Material_Attrib attrib)
|
||||
{
|
||||
return material->attribs[attrib].texture;
|
||||
}
|
|
@ -0,0 +1,828 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
static Evas_3D_Mesh_Frame *
|
||||
evas_3d_mesh_frame_new(Evas_3D_Mesh *mesh)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *frame = NULL;
|
||||
|
||||
frame = (Evas_3D_Mesh_Frame *)calloc(1, sizeof(Evas_3D_Mesh_Frame));
|
||||
|
||||
if (frame == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
frame->mesh = mesh;
|
||||
evas_box3_empty_set(&frame->aabb);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static void
|
||||
evas_3d_mesh_frame_free(Evas_3D_Mesh_Frame *frame)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (frame->material)
|
||||
{
|
||||
evas_3d_material_mesh_del(frame->material, frame->mesh);
|
||||
evas_3d_object_unreference(&frame->material->base);
|
||||
}
|
||||
|
||||
for (i = 0; i < EVAS_3D_VERTEX_ATTRIB_COUNT; i++)
|
||||
{
|
||||
if (frame->vertices[i].owns_data)
|
||||
free(frame->vertices[i].data);
|
||||
}
|
||||
|
||||
free(frame);
|
||||
}
|
||||
|
||||
static Evas_3D_Mesh_Frame *
|
||||
evas_3d_mesh_frame_find(Evas_3D_Mesh *mesh, int frame)
|
||||
{
|
||||
Eina_List *l;
|
||||
Evas_3D_Mesh_Frame *f;
|
||||
|
||||
EINA_LIST_FOREACH(mesh->frames, l, f)
|
||||
{
|
||||
if (f->frame == frame)
|
||||
return f;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mesh_init(Evas_3D_Mesh *mesh)
|
||||
{
|
||||
mesh->vertex_count = 0;
|
||||
mesh->frame_count = 0;
|
||||
mesh->frames = NULL;
|
||||
|
||||
mesh->index_format = EVAS_3D_INDEX_FORMAT_NONE;
|
||||
mesh->index_count = 0;
|
||||
mesh->indices = NULL;
|
||||
mesh->owns_indices = EINA_FALSE;
|
||||
mesh->assembly = EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES;
|
||||
|
||||
mesh->nodes = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mesh_fini(Evas_3D_Mesh *mesh)
|
||||
{
|
||||
Eina_List *l;
|
||||
Evas_3D_Mesh_Frame *f;
|
||||
|
||||
if (mesh->frames)
|
||||
{
|
||||
EINA_LIST_FOREACH(mesh->frames, l, f)
|
||||
{
|
||||
evas_3d_mesh_frame_free(f);
|
||||
}
|
||||
|
||||
eina_list_free(mesh->frames);
|
||||
}
|
||||
|
||||
if (mesh->indices && mesh->owns_indices)
|
||||
free(mesh->indices);
|
||||
|
||||
if (mesh->nodes)
|
||||
eina_hash_free(mesh->nodes);
|
||||
}
|
||||
|
||||
static void
|
||||
_mesh_free(Evas_3D_Object *obj)
|
||||
{
|
||||
Evas_3D_Mesh *mesh = (Evas_3D_Mesh *)obj;
|
||||
_mesh_fini(mesh);
|
||||
free(mesh);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_mesh_node_geometry_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
|
||||
void *data EINA_UNUSED, void *fdata)
|
||||
{
|
||||
Evas_3D_Node *n = *(Evas_3D_Node **)key;
|
||||
evas_3d_object_change(&n->base, EVAS_3D_STATE_NODE_MESH_GEOMETRY, (Evas_3D_Object *)fdata);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_mesh_node_material_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
|
||||
void *data EINA_UNUSED, void *fdata)
|
||||
{
|
||||
Evas_3D_Node *n = *(Evas_3D_Node **)key;
|
||||
evas_3d_object_change(&n->base, EVAS_3D_STATE_NODE_MESH_MATERIAL, (Evas_3D_Object *)fdata);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_mesh_change(Evas_3D_Object *obj, Evas_3D_State state, Evas_3D_Object *ref EINA_UNUSED)
|
||||
{
|
||||
Evas_3D_Mesh *mesh = (Evas_3D_Mesh *)obj;
|
||||
|
||||
if (state == EVAS_3D_STATE_MESH_MATERIAL)
|
||||
{
|
||||
if (mesh->nodes)
|
||||
eina_hash_foreach(mesh->nodes, _mesh_node_material_change_notify, obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (mesh->nodes)
|
||||
eina_hash_foreach(mesh->nodes, _mesh_node_geometry_change_notify, obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_mesh_update(Evas_3D_Object *obj)
|
||||
{
|
||||
Eina_List *l;
|
||||
Evas_3D_Mesh_Frame *f;
|
||||
Evas_3D_Mesh *mesh = (Evas_3D_Mesh *)obj;
|
||||
|
||||
EINA_LIST_FOREACH(mesh->frames, l, f)
|
||||
{
|
||||
if (f->material)
|
||||
evas_3d_object_update(&f->material->base);
|
||||
}
|
||||
}
|
||||
|
||||
static const Evas_3D_Object_Func mesh_func =
|
||||
{
|
||||
_mesh_free,
|
||||
_mesh_change,
|
||||
_mesh_update,
|
||||
};
|
||||
|
||||
void
|
||||
evas_3d_mesh_node_add(Evas_3D_Mesh *mesh, Evas_3D_Node *node)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (mesh->nodes == NULL)
|
||||
{
|
||||
mesh->nodes = eina_hash_pointer_new(NULL);
|
||||
|
||||
if (mesh->nodes == NULL)
|
||||
{
|
||||
ERR("Failed to create hash table.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
count = (int)eina_hash_find(mesh->nodes, &node);
|
||||
|
||||
eina_hash_set(mesh->nodes, &node, (const void *)(count + 1));
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_mesh_node_del(Evas_3D_Mesh *mesh, Evas_3D_Node *node)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (mesh->nodes == NULL)
|
||||
{
|
||||
ERR("No node to delete.");
|
||||
return;
|
||||
}
|
||||
|
||||
count = (int)eina_hash_find(mesh->nodes, &node);
|
||||
|
||||
if (count == 1)
|
||||
eina_hash_del(mesh->nodes, &node, NULL);
|
||||
else
|
||||
eina_hash_set(mesh->nodes, &node, (const void *)(count - 1));
|
||||
}
|
||||
|
||||
Evas_3D_Mesh *
|
||||
evas_3d_mesh_new(Evas *e)
|
||||
{
|
||||
Evas_3D_Mesh *mesh = NULL;
|
||||
|
||||
mesh = (Evas_3D_Mesh *)malloc(sizeof(Evas_3D_Mesh));
|
||||
|
||||
if (mesh == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evas_3d_object_init(&mesh->base, e, EVAS_3D_OBJECT_TYPE_MESH, &mesh_func);
|
||||
_mesh_init(mesh);
|
||||
return mesh;
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Mesh *
|
||||
evas_3d_mesh_add(Evas *e)
|
||||
{
|
||||
return evas_3d_mesh_new(e);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_del(Evas_3D_Mesh *mesh)
|
||||
{
|
||||
evas_3d_object_unreference(&mesh->base);
|
||||
}
|
||||
|
||||
EAPI Evas *
|
||||
evas_3d_mesh_evas_get(const Evas_3D_Mesh *mesh)
|
||||
{
|
||||
return mesh->base.evas;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_shade_mode_set(Evas_3D_Mesh *mesh, Evas_3D_Shade_Mode mode)
|
||||
{
|
||||
if (mesh->shade_mode != mode)
|
||||
{
|
||||
mesh->shade_mode = mode;
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_SHADE_MODE, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Shade_Mode
|
||||
evas_3d_mesh_shade_mode_get(const Evas_3D_Mesh *mesh)
|
||||
{
|
||||
return mesh->shade_mode;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_vertex_count_set(Evas_3D_Mesh *mesh, unsigned int count)
|
||||
{
|
||||
mesh->vertex_count = count;
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_VERTEX_COUNT, NULL);
|
||||
}
|
||||
|
||||
EAPI int
|
||||
evas_3d_mesh_vertex_count_get(const Evas_3D_Mesh *mesh)
|
||||
{
|
||||
return mesh->vertex_count;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_frame_add(Evas_3D_Mesh *mesh, int frame)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(mesh, frame);
|
||||
|
||||
if (f != NULL)
|
||||
{
|
||||
ERR("Already existing frame.");
|
||||
return;
|
||||
}
|
||||
|
||||
f = evas_3d_mesh_frame_new(mesh);
|
||||
|
||||
if (f == NULL)
|
||||
return;
|
||||
|
||||
f->frame = frame;
|
||||
mesh->frames = eina_list_append(mesh->frames, f);
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_FRAME, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_frame_del(Evas_3D_Mesh *mesh, int frame)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(mesh, frame);
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return;
|
||||
}
|
||||
|
||||
mesh->frames = eina_list_remove(mesh->frames, f);
|
||||
evas_3d_mesh_frame_free(f);
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_FRAME, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_frame_material_set(Evas_3D_Mesh *mesh, int frame, Evas_3D_Material *material)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(mesh, frame);
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (f->material == material)
|
||||
return;
|
||||
|
||||
if (f->material)
|
||||
{
|
||||
evas_3d_material_mesh_del(f->material, mesh);
|
||||
evas_3d_object_unreference(&f->material->base);
|
||||
}
|
||||
|
||||
f->material = material;
|
||||
evas_3d_object_reference(&material->base);
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_MATERIAL, NULL);
|
||||
evas_3d_material_mesh_add(material, mesh);
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Material *
|
||||
evas_3d_mesh_frame_material_get(const Evas_3D_Mesh *mesh, int frame)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find((Evas_3D_Mesh *)mesh, frame);
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return f->material;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_frame_vertex_data_set(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib,
|
||||
int stride, const void *data)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(mesh, frame);
|
||||
int element_count;
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (attrib == EVAS_3D_VERTEX_POSITION)
|
||||
{
|
||||
element_count = 3;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_NORMAL)
|
||||
{
|
||||
element_count = 3;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_TANGENT)
|
||||
{
|
||||
element_count = 3;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_COLOR)
|
||||
{
|
||||
element_count = 4;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_TEXCOORD)
|
||||
{
|
||||
element_count = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Invalid vertex attrib.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (f->vertices[attrib].owns_data && f->vertices[attrib].data)
|
||||
free(f->vertices[attrib].data);
|
||||
|
||||
f->vertices[attrib].size = 0;
|
||||
f->vertices[attrib].stride = stride;
|
||||
f->vertices[attrib].data = (void *)data;
|
||||
f->vertices[attrib].owns_data = EINA_FALSE;
|
||||
f->vertices[attrib].element_count = element_count;
|
||||
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_VERTEX_DATA, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_frame_vertex_data_copy_set(Evas_3D_Mesh *mesh, int frame,
|
||||
Evas_3D_Vertex_Attrib attrib,
|
||||
int stride, const void *data)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(mesh, frame);
|
||||
Evas_3D_Vertex_Buffer *vb;
|
||||
int size, element_count;
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (attrib == EVAS_3D_VERTEX_POSITION)
|
||||
{
|
||||
element_count = 3;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_NORMAL)
|
||||
{
|
||||
element_count = 3;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_TANGENT)
|
||||
{
|
||||
element_count = 3;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_COLOR)
|
||||
{
|
||||
element_count = 4;
|
||||
}
|
||||
else if (attrib == EVAS_3D_VERTEX_TEXCOORD)
|
||||
{
|
||||
element_count = 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Invalid vertex attrib.");
|
||||
return;
|
||||
}
|
||||
|
||||
vb = &f->vertices[attrib];
|
||||
size = element_count * sizeof(float) * mesh->vertex_count;
|
||||
|
||||
if (!vb->owns_data || vb->size < size)
|
||||
{
|
||||
if (vb->owns_data && vb->data)
|
||||
free(vb->data);
|
||||
|
||||
vb->data = malloc(size);
|
||||
|
||||
if (vb->data == NULL)
|
||||
{
|
||||
vb->element_count = 0;
|
||||
vb->size = 0;
|
||||
vb->stride = 0;
|
||||
vb->owns_data = EINA_FALSE;
|
||||
|
||||
ERR("Failed to allocate memory.");
|
||||
return;
|
||||
}
|
||||
|
||||
vb->size = size;
|
||||
vb->owns_data = EINA_TRUE;
|
||||
}
|
||||
|
||||
vb->element_count = element_count;
|
||||
vb->stride = 0;
|
||||
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
if (stride == 0 || stride == (int)(element_count * sizeof(float)))
|
||||
{
|
||||
memcpy(vb->data, data, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
int i;
|
||||
float *dst = (float *)vb->data;
|
||||
float *src = (float *)data;
|
||||
|
||||
if (element_count == 1)
|
||||
{
|
||||
for (i = 0; i <mesh->vertex_count; i++)
|
||||
{
|
||||
*dst++ = src[0];
|
||||
|
||||
src = (float *)((char *)src + stride);
|
||||
}
|
||||
}
|
||||
else if (element_count == 2)
|
||||
{
|
||||
for (i = 0; i <mesh->vertex_count; i++)
|
||||
{
|
||||
*dst++ = src[0];
|
||||
*dst++ = src[1];
|
||||
|
||||
src = (float *)((char *)src + stride);
|
||||
}
|
||||
}
|
||||
else if (element_count == 3)
|
||||
{
|
||||
for (i = 0; i <mesh->vertex_count; i++)
|
||||
{
|
||||
*dst++ = src[0];
|
||||
*dst++ = src[1];
|
||||
*dst++ = src[2];
|
||||
|
||||
src = (float *)((char *)src + stride);
|
||||
}
|
||||
}
|
||||
else if (element_count == 4)
|
||||
{
|
||||
for (i = 0; i <mesh->vertex_count; i++)
|
||||
{
|
||||
*dst++ = src[0];
|
||||
*dst++ = src[1];
|
||||
*dst++ = src[2];
|
||||
*dst++ = src[3];
|
||||
|
||||
src = (float *)((char *)src + stride);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_VERTEX_DATA, NULL);
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
evas_3d_mesh_frame_vertex_data_map(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(mesh, frame);
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (f->vertices[attrib].mapped)
|
||||
{
|
||||
ERR("Try to map alreadly mapped data.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f->vertices[attrib].mapped = EINA_TRUE;
|
||||
return f->vertices[attrib].data;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_frame_vertex_data_unmap(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find(mesh, frame);
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!f->vertices[attrib].mapped)
|
||||
{
|
||||
ERR("Try to unmap data which is not mapped yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
f->vertices[attrib].mapped = EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
evas_3d_mesh_frame_vertex_stride_get(const Evas_3D_Mesh *mesh, int frame,
|
||||
Evas_3D_Vertex_Attrib attrib)
|
||||
{
|
||||
Evas_3D_Mesh_Frame *f = evas_3d_mesh_frame_find((Evas_3D_Mesh *)mesh, frame);
|
||||
|
||||
if (f == NULL)
|
||||
{
|
||||
ERR("Not existing mesh frame.");
|
||||
return 0;
|
||||
}
|
||||
|
||||
return f->vertices[attrib].stride;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_index_data_set(Evas_3D_Mesh *mesh, Evas_3D_Index_Format format, int count,
|
||||
const void *indices)
|
||||
{
|
||||
if (mesh->owns_indices && mesh->indices)
|
||||
free(mesh->indices);
|
||||
|
||||
mesh->index_format = format;
|
||||
mesh->index_count = count;
|
||||
mesh->index_size = 0;
|
||||
mesh->indices = (void *)indices;
|
||||
mesh->owns_indices = EINA_FALSE;
|
||||
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_INDEX_DATA, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_index_data_copy_set(Evas_3D_Mesh *mesh, Evas_3D_Index_Format format, int count, const void *indices)
|
||||
{
|
||||
int size;
|
||||
|
||||
if (format == EVAS_3D_INDEX_FORMAT_UNSIGNED_BYTE)
|
||||
{
|
||||
size = count * sizeof(unsigned char);
|
||||
}
|
||||
else if (format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
{
|
||||
size = count * sizeof(unsigned short);
|
||||
}
|
||||
else
|
||||
{
|
||||
ERR("Invalid index format.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mesh->owns_indices || mesh->index_size < size)
|
||||
{
|
||||
if (mesh->owns_indices && mesh->indices)
|
||||
free(mesh->indices);
|
||||
|
||||
mesh->indices = malloc(size);
|
||||
|
||||
if (mesh->indices == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return;
|
||||
}
|
||||
|
||||
mesh->index_size = size;
|
||||
mesh->owns_indices = EINA_TRUE;
|
||||
}
|
||||
|
||||
mesh->index_format = format;
|
||||
mesh->index_count = count;
|
||||
|
||||
if (indices)
|
||||
memcpy(mesh->indices, indices, size);
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Index_Format
|
||||
evas_3d_mesh_index_format_get(const Evas_3D_Mesh *mesh)
|
||||
{
|
||||
return mesh->index_format;
|
||||
}
|
||||
|
||||
EAPI int
|
||||
evas_3d_mesh_index_count_get(const Evas_3D_Mesh *mesh)
|
||||
{
|
||||
return mesh->index_count;
|
||||
}
|
||||
|
||||
EAPI void *
|
||||
evas_3d_mesh_index_data_map(Evas_3D_Mesh *mesh)
|
||||
{
|
||||
if (mesh->index_mapped)
|
||||
{
|
||||
ERR("Try to map alreadly mapped data.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mesh->index_mapped = EINA_TRUE;
|
||||
return mesh->indices;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_index_data_unmap(Evas_3D_Mesh *mesh)
|
||||
{
|
||||
if (!mesh->index_mapped)
|
||||
{
|
||||
ERR("Try to unmap data which is not mapped yet.");
|
||||
return;
|
||||
}
|
||||
|
||||
mesh->index_mapped = EINA_FALSE;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_vertex_assembly_set(Evas_3D_Mesh *mesh, Evas_3D_Vertex_Assembly assembly)
|
||||
{
|
||||
mesh->assembly = assembly;
|
||||
evas_3d_object_change(&mesh->base, EVAS_3D_STATE_MESH_VERTEX_ASSEMBLY, NULL);
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Vertex_Assembly
|
||||
evas_3d_mesh_vertex_assembly_get(const Evas_3D_Mesh *mesh)
|
||||
{
|
||||
return mesh->assembly;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_mesh_file_set(Evas_3D_Mesh *mesh, Evas_3D_Mesh_File_Type type,
|
||||
const char *file, const char *key EINA_UNUSED)
|
||||
{
|
||||
_mesh_fini(mesh);
|
||||
_mesh_init(mesh);
|
||||
|
||||
if (file == NULL)
|
||||
return;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case EVAS_3D_MESH_FILE_TYPE_MD2:
|
||||
evas_3d_mesh_file_md2_set(mesh, file);
|
||||
break;
|
||||
default:
|
||||
ERR("Invalid mesh file type.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_mesh_frame_find(Evas_3D_Mesh *mesh, int frame,
|
||||
Eina_List **l, Eina_List **r)
|
||||
{
|
||||
Eina_List *left, *right;
|
||||
Evas_3D_Mesh_Frame *f0, *f1;
|
||||
|
||||
left = mesh->frames;
|
||||
right = eina_list_next(left);
|
||||
|
||||
while (right)
|
||||
{
|
||||
f0 = (Evas_3D_Mesh_Frame *)eina_list_data_get(left);
|
||||
f1 = (Evas_3D_Mesh_Frame *)eina_list_data_get(right);
|
||||
|
||||
if (frame >= f0->frame && frame <= f1->frame)
|
||||
break;
|
||||
|
||||
left = right;
|
||||
right = eina_list_next(left);
|
||||
}
|
||||
|
||||
if (right == NULL)
|
||||
{
|
||||
if (frame <= f0->frame)
|
||||
{
|
||||
*l = NULL;
|
||||
*r = left;
|
||||
}
|
||||
else
|
||||
{
|
||||
*l = left;
|
||||
*r = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
*l = left;
|
||||
*r = right;
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_mesh_interpolate_vertex_buffer_get(Evas_3D_Mesh *mesh, int frame,
|
||||
Evas_3D_Vertex_Attrib attrib,
|
||||
Evas_3D_Vertex_Buffer *buf0,
|
||||
Evas_3D_Vertex_Buffer *buf1,
|
||||
Evas_Real *weight)
|
||||
{
|
||||
Eina_List *l, *r;
|
||||
const Evas_3D_Mesh_Frame *f0 = NULL, *f1 = NULL;
|
||||
|
||||
_mesh_frame_find(mesh, frame, &l, &r);
|
||||
|
||||
while (l)
|
||||
{
|
||||
f0 = (const Evas_3D_Mesh_Frame *)eina_list_data_get(l);
|
||||
|
||||
if (f0->vertices[attrib].data != NULL)
|
||||
break;
|
||||
|
||||
l = eina_list_prev(l);
|
||||
f0 = NULL;
|
||||
}
|
||||
|
||||
while (r)
|
||||
{
|
||||
f1 = (const Evas_3D_Mesh_Frame *)eina_list_data_get(r);
|
||||
|
||||
if (f1->vertices[attrib].data != NULL)
|
||||
break;
|
||||
|
||||
r = eina_list_next(r);
|
||||
f1 = NULL;
|
||||
}
|
||||
|
||||
if (f0 == NULL && f1 == NULL)
|
||||
return;
|
||||
|
||||
if (f0 == NULL)
|
||||
{
|
||||
f0 = f1;
|
||||
}
|
||||
else if (f1 != NULL)
|
||||
{
|
||||
if (frame == f0->frame)
|
||||
{
|
||||
f1 = NULL;
|
||||
}
|
||||
else if (frame == f1->frame)
|
||||
{
|
||||
f0 = f1;
|
||||
f1 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
buf0->data = f0->vertices[attrib].data;
|
||||
buf0->stride = f0->vertices[attrib].stride;
|
||||
buf0->size = f0->vertices[attrib].size;
|
||||
|
||||
if (f1)
|
||||
{
|
||||
buf1->data = f1->vertices[attrib].data;
|
||||
buf1->stride = f1->vertices[attrib].stride;
|
||||
buf1->size = f1->vertices[attrib].size;
|
||||
|
||||
*weight = (f1->frame - frame) / (Evas_Real)(f1->frame - f0->frame);
|
||||
}
|
||||
else
|
||||
{
|
||||
buf1->data = NULL;
|
||||
buf1->stride = 0;
|
||||
buf1->size = 0;
|
||||
|
||||
*weight = 1.0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,440 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
#define PACKED __attribute__((__packed__))
|
||||
|
||||
#define MD2_MAGIC_NUMBER 844121161
|
||||
#define MD2_VERSION 8
|
||||
#define MD2_FRAME_SCALE 256
|
||||
|
||||
/* Structures for reading data from file. */
|
||||
typedef struct _MD2_Header MD2_Header;
|
||||
typedef struct _MD2_Vertex MD2_Vertex;
|
||||
typedef struct _MD2_Frame MD2_Frame;
|
||||
typedef struct _MD2_Triangle MD2_Triangle;
|
||||
typedef struct _MD2_Texcoord MD2_Texcoord;
|
||||
|
||||
struct PACKED _MD2_Header
|
||||
{
|
||||
int magic;
|
||||
int version;
|
||||
|
||||
int skin_width;
|
||||
int skin_height;
|
||||
|
||||
int frame_size;
|
||||
|
||||
int skins_count;
|
||||
int vertex_count;
|
||||
int texcoord_count;
|
||||
int triangle_count;
|
||||
int glcmd_count;
|
||||
int frame_count;
|
||||
|
||||
int offset_skins;
|
||||
int offset_texcoords;
|
||||
int offset_triangles;
|
||||
int offset_frames;
|
||||
int offset_glcmds;
|
||||
int offset_end;
|
||||
};
|
||||
|
||||
struct PACKED _MD2_Vertex
|
||||
{
|
||||
unsigned char pos[3];
|
||||
unsigned char normal_idx;
|
||||
};
|
||||
|
||||
struct PACKED _MD2_Frame
|
||||
{
|
||||
float scale[3];
|
||||
float trans[3];
|
||||
char name[16];
|
||||
MD2_Vertex vertices[1];
|
||||
};
|
||||
|
||||
struct PACKED _MD2_Triangle
|
||||
{
|
||||
unsigned short vertex_idx[3];
|
||||
unsigned short texcoord_idx[3];
|
||||
};
|
||||
|
||||
struct PACKED _MD2_Texcoord
|
||||
{
|
||||
short s;
|
||||
short t;
|
||||
};
|
||||
|
||||
typedef struct _MD2_Loader
|
||||
{
|
||||
Eina_File *file;
|
||||
char *map;
|
||||
int size;
|
||||
|
||||
int skin_width;
|
||||
int skin_height;
|
||||
|
||||
int frame_count;
|
||||
int frame_size;
|
||||
char *frames;
|
||||
|
||||
int vertex_count;
|
||||
int triangle_count;
|
||||
int texcoord_count;
|
||||
|
||||
MD2_Triangle *triangles;
|
||||
MD2_Texcoord *texcoords;
|
||||
} MD2_Loader;
|
||||
|
||||
static const float normal_table[162][3] =
|
||||
{
|
||||
{-0.525731f, 0.000000f, 0.850651f},
|
||||
{-0.442863f, 0.238856f, 0.864188f},
|
||||
{-0.295242f, 0.000000f, 0.955423f},
|
||||
{-0.309017f, 0.500000f, 0.809017f},
|
||||
{-0.162460f, 0.262866f, 0.951056f},
|
||||
{ 0.000000f, 0.000000f, 1.000000f},
|
||||
{ 0.000000f, 0.850651f, 0.525731f},
|
||||
{-0.147621f, 0.716567f, 0.681718f},
|
||||
{ 0.147621f, 0.716567f, 0.681718f},
|
||||
{ 0.000000f, 0.525731f, 0.850651f},
|
||||
{ 0.309017f, 0.500000f, 0.809017f},
|
||||
{ 0.525731f, 0.000000f, 0.850651f},
|
||||
{ 0.295242f, 0.000000f, 0.955423f},
|
||||
{ 0.442863f, 0.238856f, 0.864188f},
|
||||
{ 0.162460f, 0.262866f, 0.951056f},
|
||||
{-0.681718f, 0.147621f, 0.716567f},
|
||||
{-0.809017f, 0.309017f, 0.500000f},
|
||||
{-0.587785f, 0.425325f, 0.688191f},
|
||||
{-0.850651f, 0.525731f, 0.000000f},
|
||||
{-0.864188f, 0.442863f, 0.238856f},
|
||||
{-0.716567f, 0.681718f, 0.147621f},
|
||||
{-0.688191f, 0.587785f, 0.425325f},
|
||||
{-0.500000f, 0.809017f, 0.309017f},
|
||||
{-0.238856f, 0.864188f, 0.442863f},
|
||||
{-0.425325f, 0.688191f, 0.587785f},
|
||||
{-0.716567f, 0.681718f, -0.147621f},
|
||||
{-0.500000f, 0.809017f, -0.309017f},
|
||||
{-0.525731f, 0.850651f, 0.000000f},
|
||||
{ 0.000000f, 0.850651f, -0.525731f},
|
||||
{-0.238856f, 0.864188f, -0.442863f},
|
||||
{ 0.000000f, 0.955423f, -0.295242f},
|
||||
{-0.262866f, 0.951056f, -0.162460f},
|
||||
{ 0.000000f, 1.000000f, 0.000000f},
|
||||
{ 0.000000f, 0.955423f, 0.295242f},
|
||||
{-0.262866f, 0.951056f, 0.162460f},
|
||||
{ 0.238856f, 0.864188f, 0.442863f},
|
||||
{ 0.262866f, 0.951056f, 0.162460f},
|
||||
{ 0.500000f, 0.809017f, 0.309017f},
|
||||
{ 0.238856f, 0.864188f, -0.442863f},
|
||||
{ 0.262866f, 0.951056f, -0.162460f},
|
||||
{ 0.500000f, 0.809017f, -0.309017f},
|
||||
{ 0.850651f, 0.525731f, 0.000000f},
|
||||
{ 0.716567f, 0.681718f, 0.147621f},
|
||||
{ 0.716567f, 0.681718f, -0.147621f},
|
||||
{ 0.525731f, 0.850651f, 0.000000f},
|
||||
{ 0.425325f, 0.688191f, 0.587785f},
|
||||
{ 0.864188f, 0.442863f, 0.238856f},
|
||||
{ 0.688191f, 0.587785f, 0.425325f},
|
||||
{ 0.809017f, 0.309017f, 0.500000f},
|
||||
{ 0.681718f, 0.147621f, 0.716567f},
|
||||
{ 0.587785f, 0.425325f, 0.688191f},
|
||||
{ 0.955423f, 0.295242f, 0.000000f},
|
||||
{ 1.000000f, 0.000000f, 0.000000f},
|
||||
{ 0.951056f, 0.162460f, 0.262866f},
|
||||
{ 0.850651f, -0.525731f, 0.000000f},
|
||||
{ 0.955423f, -0.295242f, 0.000000f},
|
||||
{ 0.864188f, -0.442863f, 0.238856f},
|
||||
{ 0.951056f, -0.162460f, 0.262866f},
|
||||
{ 0.809017f, -0.309017f, 0.500000f},
|
||||
{ 0.681718f, -0.147621f, 0.716567f},
|
||||
{ 0.850651f, 0.000000f, 0.525731f},
|
||||
{ 0.864188f, 0.442863f, -0.238856f},
|
||||
{ 0.809017f, 0.309017f, -0.500000f},
|
||||
{ 0.951056f, 0.162460f, -0.262866f},
|
||||
{ 0.525731f, 0.000000f, -0.850651f},
|
||||
{ 0.681718f, 0.147621f, -0.716567f},
|
||||
{ 0.681718f, -0.147621f, -0.716567f},
|
||||
{ 0.850651f, 0.000000f, -0.525731f},
|
||||
{ 0.809017f, -0.309017f, -0.500000f},
|
||||
{ 0.864188f, -0.442863f, -0.238856f},
|
||||
{ 0.951056f, -0.162460f, -0.262866f},
|
||||
{ 0.147621f, 0.716567f, -0.681718f},
|
||||
{ 0.309017f, 0.500000f, -0.809017f},
|
||||
{ 0.425325f, 0.688191f, -0.587785f},
|
||||
{ 0.442863f, 0.238856f, -0.864188f},
|
||||
{ 0.587785f, 0.425325f, -0.688191f},
|
||||
{ 0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.147621f, 0.716567f, -0.681718f},
|
||||
{-0.309017f, 0.500000f, -0.809017f},
|
||||
{ 0.000000f, 0.525731f, -0.850651f},
|
||||
{-0.525731f, 0.000000f, -0.850651f},
|
||||
{-0.442863f, 0.238856f, -0.864188f},
|
||||
{-0.295242f, 0.000000f, -0.955423f},
|
||||
{-0.162460f, 0.262866f, -0.951056f},
|
||||
{ 0.000000f, 0.000000f, -1.000000f},
|
||||
{ 0.295242f, 0.000000f, -0.955423f},
|
||||
{ 0.162460f, 0.262866f, -0.951056f},
|
||||
{-0.442863f, -0.238856f, -0.864188f},
|
||||
{-0.309017f, -0.500000f, -0.809017f},
|
||||
{-0.162460f, -0.262866f, -0.951056f},
|
||||
{ 0.000000f, -0.850651f, -0.525731f},
|
||||
{-0.147621f, -0.716567f, -0.681718f},
|
||||
{ 0.147621f, -0.716567f, -0.681718f},
|
||||
{ 0.000000f, -0.525731f, -0.850651f},
|
||||
{ 0.309017f, -0.500000f, -0.809017f},
|
||||
{ 0.442863f, -0.238856f, -0.864188f},
|
||||
{ 0.162460f, -0.262866f, -0.951056f},
|
||||
{ 0.238856f, -0.864188f, -0.442863f},
|
||||
{ 0.500000f, -0.809017f, -0.309017f},
|
||||
{ 0.425325f, -0.688191f, -0.587785f},
|
||||
{ 0.716567f, -0.681718f, -0.147621f},
|
||||
{ 0.688191f, -0.587785f, -0.425325f},
|
||||
{ 0.587785f, -0.425325f, -0.688191f},
|
||||
{ 0.000000f, -0.955423f, -0.295242f},
|
||||
{ 0.000000f, -1.000000f, 0.000000f},
|
||||
{ 0.262866f, -0.951056f, -0.162460f},
|
||||
{ 0.000000f, -0.850651f, 0.525731f},
|
||||
{ 0.000000f, -0.955423f, 0.295242f},
|
||||
{ 0.238856f, -0.864188f, 0.442863f},
|
||||
{ 0.262866f, -0.951056f, 0.162460f},
|
||||
{ 0.500000f, -0.809017f, 0.309017f},
|
||||
{ 0.716567f, -0.681718f, 0.147621f},
|
||||
{ 0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.238856f, -0.864188f, -0.442863f},
|
||||
{-0.500000f, -0.809017f, -0.309017f},
|
||||
{-0.262866f, -0.951056f, -0.162460f},
|
||||
{-0.850651f, -0.525731f, 0.000000f},
|
||||
{-0.716567f, -0.681718f, -0.147621f},
|
||||
{-0.716567f, -0.681718f, 0.147621f},
|
||||
{-0.525731f, -0.850651f, 0.000000f},
|
||||
{-0.500000f, -0.809017f, 0.309017f},
|
||||
{-0.238856f, -0.864188f, 0.442863f},
|
||||
{-0.262866f, -0.951056f, 0.162460f},
|
||||
{-0.864188f, -0.442863f, 0.238856f},
|
||||
{-0.809017f, -0.309017f, 0.500000f},
|
||||
{-0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.681718f, -0.147621f, 0.716567f},
|
||||
{-0.442863f, -0.238856f, 0.864188f},
|
||||
{-0.587785f, -0.425325f, 0.688191f},
|
||||
{-0.309017f, -0.500000f, 0.809017f},
|
||||
{-0.147621f, -0.716567f, 0.681718f},
|
||||
{-0.425325f, -0.688191f, 0.587785f},
|
||||
{-0.162460f, -0.262866f, 0.951056f},
|
||||
{ 0.442863f, -0.238856f, 0.864188f},
|
||||
{ 0.162460f, -0.262866f, 0.951056f},
|
||||
{ 0.309017f, -0.500000f, 0.809017f},
|
||||
{ 0.147621f, -0.716567f, 0.681718f},
|
||||
{ 0.000000f, -0.525731f, 0.850651f},
|
||||
{ 0.425325f, -0.688191f, 0.587785f},
|
||||
{ 0.587785f, -0.425325f, 0.688191f},
|
||||
{ 0.688191f, -0.587785f, 0.425325f},
|
||||
{-0.955423f, 0.295242f, 0.000000f},
|
||||
{-0.951056f, 0.162460f, 0.262866f},
|
||||
{-1.000000f, 0.000000f, 0.000000f},
|
||||
{-0.850651f, 0.000000f, 0.525731f},
|
||||
{-0.955423f, -0.295242f, 0.000000f},
|
||||
{-0.951056f, -0.162460f, 0.262866f},
|
||||
{-0.864188f, 0.442863f, -0.238856f},
|
||||
{-0.951056f, 0.162460f, -0.262866f},
|
||||
{-0.809017f, 0.309017f, -0.500000f},
|
||||
{-0.864188f, -0.442863f, -0.238856f},
|
||||
{-0.951056f, -0.162460f, -0.262866f},
|
||||
{-0.809017f, -0.309017f, -0.500000f},
|
||||
{-0.681718f, 0.147621f, -0.716567f},
|
||||
{-0.681718f, -0.147621f, -0.716567f},
|
||||
{-0.850651f, 0.000000f, -0.525731f},
|
||||
{-0.688191f, 0.587785f, -0.425325f},
|
||||
{-0.587785f, 0.425325f, -0.688191f},
|
||||
{-0.425325f, 0.688191f, -0.587785f},
|
||||
{-0.425325f, -0.688191f, -0.587785f},
|
||||
{-0.587785f, -0.425325f, -0.688191f},
|
||||
{-0.688191f, -0.587785f, -0.425325f},
|
||||
};
|
||||
|
||||
static inline void
|
||||
_md2_loader_fini(MD2_Loader *loader)
|
||||
{
|
||||
if (loader->map)
|
||||
{
|
||||
eina_file_map_free(loader->file, loader->map);
|
||||
loader->map = NULL;
|
||||
}
|
||||
|
||||
if (loader->file)
|
||||
{
|
||||
eina_file_close(loader->file);
|
||||
loader->file = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_md2_loader_init(MD2_Loader *loader, const char *file)
|
||||
{
|
||||
MD2_Header header;
|
||||
|
||||
memset(loader, 0x00, sizeof(MD2_Loader));
|
||||
|
||||
/* Open given file. */
|
||||
loader->file = eina_file_open(file, 0);
|
||||
|
||||
if (loader->file == NULL)
|
||||
{
|
||||
ERR("Failed to open file %s\n", file);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Check file size. We require a file larger than MD2 header size. */
|
||||
loader->size = eina_file_size_get(loader->file);
|
||||
|
||||
if (loader->size < (int)sizeof(MD2_Header))
|
||||
goto error;
|
||||
|
||||
/* Map the file. */
|
||||
loader->map = eina_file_map_all(loader->file, EINA_FILE_SEQUENTIAL);
|
||||
|
||||
if (loader->map == NULL)
|
||||
goto error;
|
||||
|
||||
/* Read header. */
|
||||
memcpy(&header, loader->map, sizeof(MD2_Header));
|
||||
|
||||
/* Check identity */
|
||||
if (header.magic != MD2_MAGIC_NUMBER || header.version != MD2_VERSION)
|
||||
goto error;
|
||||
|
||||
/* Check offsets */
|
||||
if (header.offset_skins > header.offset_end)
|
||||
goto error;
|
||||
|
||||
if (header.offset_texcoords > header.offset_end)
|
||||
goto error;
|
||||
|
||||
if (header.offset_triangles > header.offset_end)
|
||||
goto error;
|
||||
|
||||
if (header.offset_frames > header.offset_end)
|
||||
goto error;
|
||||
|
||||
if (header.offset_glcmds > header.offset_end)
|
||||
goto error;
|
||||
|
||||
if (header.offset_end > loader->size)
|
||||
goto error;
|
||||
|
||||
loader->skin_width = header.skin_width;
|
||||
loader->skin_height = header.skin_height;
|
||||
|
||||
loader->frame_count = header.frame_count;
|
||||
loader->frame_size = header.frame_size;
|
||||
loader->frames = loader->map + header.offset_frames;
|
||||
|
||||
loader->vertex_count = header.vertex_count;
|
||||
loader->triangle_count = header.triangle_count;
|
||||
loader->texcoord_count = header.texcoord_count;
|
||||
|
||||
loader->triangles = (MD2_Triangle *)(loader->map + header.offset_triangles);
|
||||
loader->texcoords = (MD2_Texcoord *)(loader->map + header.offset_texcoords);
|
||||
return EINA_TRUE;
|
||||
|
||||
error:
|
||||
_md2_loader_fini(loader);
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_mesh_file_md2_set(Evas_3D_Mesh *mesh, const char *file)
|
||||
{
|
||||
MD2_Loader loader;
|
||||
int i, j, k;
|
||||
float *pos, *nor, *tex;
|
||||
int stride_pos, stride_nor, stride_tex;
|
||||
float s_scale, t_scale;
|
||||
|
||||
/* Initialize MD2 loader (Open file and read MD2 head ant etc) */
|
||||
if (!_md2_loader_init(&loader, file))
|
||||
{
|
||||
ERR("Failed to initialize MD2 loader.");
|
||||
return;
|
||||
}
|
||||
|
||||
s_scale = 1.0 / (float)(loader.skin_width - 1);
|
||||
t_scale = 1.0 / (float)(loader.skin_height - 1);
|
||||
|
||||
evas_3d_mesh_vertex_count_set(mesh, loader.triangle_count * 3);
|
||||
evas_3d_mesh_vertex_assembly_set(mesh, EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES);
|
||||
|
||||
/* Load frames */
|
||||
for (i = 0; i < loader.frame_count; i++)
|
||||
{
|
||||
const MD2_Frame *frame = (const MD2_Frame *)(loader.frames + loader.frame_size * i);
|
||||
int f = i * MD2_FRAME_SCALE;
|
||||
|
||||
/* Add a mesh frame. */
|
||||
evas_3d_mesh_frame_add(mesh, f);
|
||||
|
||||
/* Allocate vertex buffer for the frame. */
|
||||
evas_3d_mesh_frame_vertex_data_copy_set(mesh, f, EVAS_3D_VERTEX_POSITION, 0, NULL);
|
||||
evas_3d_mesh_frame_vertex_data_copy_set(mesh, f, EVAS_3D_VERTEX_NORMAL, 0, NULL);
|
||||
evas_3d_mesh_frame_vertex_data_copy_set(mesh, f, EVAS_3D_VERTEX_TEXCOORD, 0, NULL);
|
||||
|
||||
/* Map vertex buffer. */
|
||||
pos = (float *)evas_3d_mesh_frame_vertex_data_map(mesh, f, EVAS_3D_VERTEX_POSITION);
|
||||
nor = (float *)evas_3d_mesh_frame_vertex_data_map(mesh, f, EVAS_3D_VERTEX_NORMAL);
|
||||
tex = (float *)evas_3d_mesh_frame_vertex_data_map(mesh, f, EVAS_3D_VERTEX_TEXCOORD);
|
||||
|
||||
stride_pos = evas_3d_mesh_frame_vertex_stride_get(mesh, f, EVAS_3D_VERTEX_POSITION);
|
||||
stride_nor = evas_3d_mesh_frame_vertex_stride_get(mesh, f, EVAS_3D_VERTEX_NORMAL);
|
||||
stride_tex = evas_3d_mesh_frame_vertex_stride_get(mesh, f, EVAS_3D_VERTEX_TEXCOORD);
|
||||
|
||||
if (stride_pos == 0)
|
||||
stride_pos = sizeof(float) * 3;
|
||||
|
||||
if (stride_nor == 0)
|
||||
stride_nor = sizeof(float) * 3;
|
||||
|
||||
if (stride_tex == 0)
|
||||
stride_tex = sizeof(float) * 2;
|
||||
|
||||
for (j = 0; j < loader.triangle_count; j++)
|
||||
{
|
||||
const MD2_Triangle *tri = &loader.triangles[j];
|
||||
|
||||
for (k = 0; k < 3; k++)
|
||||
{
|
||||
unsigned int tidx, vidx;
|
||||
float *p, *n, *t;
|
||||
|
||||
tidx = tri->texcoord_idx[k];
|
||||
vidx = tri->vertex_idx[k];
|
||||
|
||||
p = (float *)((char *)pos + stride_pos * (j * 3 + k));
|
||||
n = (float *)((char *)nor + stride_nor * (j * 3 + k));
|
||||
t = (float *)((char *)tex + stride_tex * (j * 3 + k));
|
||||
|
||||
p[0] = frame->vertices[vidx].pos[0] * frame->scale[0] + frame->trans[0];
|
||||
p[1] = frame->vertices[vidx].pos[1] * frame->scale[1] + frame->trans[1];
|
||||
p[2] = frame->vertices[vidx].pos[2] * frame->scale[2] + frame->trans[2];
|
||||
|
||||
n[0] = normal_table[frame->vertices[vidx].normal_idx][0];
|
||||
n[1] = normal_table[frame->vertices[vidx].normal_idx][1];
|
||||
n[2] = normal_table[frame->vertices[vidx].normal_idx][2];
|
||||
|
||||
t[0] = loader.texcoords[tidx].s * s_scale;
|
||||
t[1] = 1.0 - loader.texcoords[tidx].t * t_scale;
|
||||
}
|
||||
}
|
||||
|
||||
/* Unmap vertex buffer. */
|
||||
evas_3d_mesh_frame_vertex_data_unmap(mesh, f, EVAS_3D_VERTEX_POSITION);
|
||||
evas_3d_mesh_frame_vertex_data_unmap(mesh, f, EVAS_3D_VERTEX_NORMAL);
|
||||
evas_3d_mesh_frame_vertex_data_unmap(mesh, f, EVAS_3D_VERTEX_TEXCOORD);
|
||||
}
|
||||
|
||||
_md2_loader_fini(&loader);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,129 @@
|
|||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
#define REF_COUNT_CHECK(obj) \
|
||||
do { \
|
||||
if ((obj)->ref_count < 1) \
|
||||
{ \
|
||||
ERR("Invalid reference count.")
|
||||
|
||||
#define REF_COUNT_CHECK_END() \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define OBJ_TYPE_CHECK(obj, type) \
|
||||
do { \
|
||||
if ((obj)->type != type) \
|
||||
{ \
|
||||
ERR("3D object type check failed.")
|
||||
|
||||
#define OBJ_TYPE_CHECK_END() \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
void
|
||||
evas_3d_object_init(Evas_3D_Object *obj,
|
||||
Evas *e, Evas_3D_Object_Type type, const Evas_3D_Object_Func *func)
|
||||
{
|
||||
obj->evas = e;
|
||||
obj->type = type;
|
||||
obj->ref_count = 1;
|
||||
obj->func = *func;
|
||||
memset(&obj->dirty[0], 0x00, sizeof(Eina_Bool) * EVAS_3D_STATE_MAX);
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_object_reference(Evas_3D_Object *obj)
|
||||
{
|
||||
REF_COUNT_CHECK(obj);
|
||||
return;
|
||||
REF_COUNT_CHECK_END();
|
||||
|
||||
obj->ref_count++;
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_object_unreference(Evas_3D_Object *obj)
|
||||
{
|
||||
if (obj->ref_count < 1)
|
||||
{
|
||||
printf("gotcha\n");
|
||||
}
|
||||
|
||||
REF_COUNT_CHECK(obj);
|
||||
return;
|
||||
REF_COUNT_CHECK_END();
|
||||
|
||||
obj->ref_count--;
|
||||
|
||||
if (obj->ref_count == 0)
|
||||
obj->func.free(obj);
|
||||
}
|
||||
|
||||
int
|
||||
evas_3d_object_reference_count_get(const Evas_3D_Object *obj)
|
||||
{
|
||||
REF_COUNT_CHECK(obj);
|
||||
return 0;
|
||||
REF_COUNT_CHECK_END();
|
||||
|
||||
return obj->ref_count;
|
||||
}
|
||||
|
||||
Evas *
|
||||
evas_3d_object_evas_get(const Evas_3D_Object *obj)
|
||||
{
|
||||
REF_COUNT_CHECK(obj);
|
||||
return NULL;
|
||||
REF_COUNT_CHECK_END();
|
||||
|
||||
return obj->evas;
|
||||
}
|
||||
|
||||
Evas_3D_Object_Type
|
||||
evas_3d_object_type_get(const Evas_3D_Object *obj)
|
||||
{
|
||||
REF_COUNT_CHECK(obj);
|
||||
return EVAS_3D_OBJECT_TYPE_INVALID;
|
||||
REF_COUNT_CHECK_END();
|
||||
|
||||
return obj->type;
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
evas_3d_object_dirty_get(const Evas_3D_Object *obj, Evas_3D_State state)
|
||||
{
|
||||
return obj->dirty[state];
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_object_change(Evas_3D_Object *obj, Evas_3D_State state, Evas_3D_Object *ref)
|
||||
{
|
||||
/* Skip already dirty properties. */
|
||||
if (obj->dirty[state])
|
||||
return;
|
||||
|
||||
obj->dirty[state] = EINA_TRUE;
|
||||
obj->dirty[EVAS_3D_STATE_ANY] = EINA_TRUE;
|
||||
|
||||
if (obj->func.change)
|
||||
obj->func.change(obj, state, ref);
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_object_update(Evas_3D_Object *obj)
|
||||
{
|
||||
if (!obj->dirty[EVAS_3D_STATE_ANY])
|
||||
return;
|
||||
|
||||
if (obj->func.update)
|
||||
obj->func.update(obj);
|
||||
|
||||
evas_3d_object_update_done(obj);
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_object_update_done(Evas_3D_Object *obj)
|
||||
{
|
||||
memset(&obj->dirty[0], 0x00, sizeof(Eina_Bool) * EVAS_3D_STATE_MAX);
|
||||
}
|
|
@ -0,0 +1,622 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
void
|
||||
evas_3d_scene_data_init(Evas_3D_Scene_Data *data)
|
||||
{
|
||||
data->camera_node = NULL;
|
||||
data->light_nodes = NULL;
|
||||
data->mesh_nodes = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_scene_data_fini(Evas_3D_Scene_Data *data)
|
||||
{
|
||||
if (data->light_nodes)
|
||||
eina_list_free(data->light_nodes);
|
||||
|
||||
if (data->mesh_nodes)
|
||||
eina_list_free(data->mesh_nodes);
|
||||
}
|
||||
|
||||
static void
|
||||
_scene_change(Evas_3D_Object *obj, Evas_3D_State state EINA_UNUSED, Evas_3D_Object *ref EINA_UNUSED)
|
||||
{
|
||||
Evas_3D_Scene *scene = (Evas_3D_Scene *)obj;
|
||||
Eina_List *l;
|
||||
Evas_Object *eo;
|
||||
|
||||
EINA_LIST_FOREACH(scene->images, l, eo)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo, EVAS_OBJ_CLASS);
|
||||
evas_object_change(eo, obj);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_scene_update(Evas_3D_Object *obj)
|
||||
{
|
||||
Evas_3D_Scene *scene = (Evas_3D_Scene *)obj;
|
||||
|
||||
if (scene->root_node)
|
||||
evas_3d_object_update(&scene->root_node->base);
|
||||
|
||||
if (scene->camera_node)
|
||||
evas_3d_object_update(&scene->camera_node->base);
|
||||
}
|
||||
|
||||
static void
|
||||
_scene_free(Evas_3D_Object *obj)
|
||||
{
|
||||
Evas_3D_Scene *scene = (Evas_3D_Scene *)obj;
|
||||
|
||||
if (scene->root_node)
|
||||
{
|
||||
evas_3d_node_scene_root_del(scene->root_node, scene);
|
||||
evas_3d_object_unreference(&scene->root_node->base);
|
||||
}
|
||||
|
||||
if (scene->camera_node)
|
||||
{
|
||||
evas_3d_node_scene_camera_del(scene->camera_node, scene);
|
||||
evas_3d_object_unreference(&scene->camera_node->base);
|
||||
}
|
||||
|
||||
if (scene->images)
|
||||
eina_list_free(scene->images);
|
||||
|
||||
free(scene);
|
||||
}
|
||||
|
||||
static const Evas_3D_Object_Func scene_func =
|
||||
{
|
||||
_scene_free,
|
||||
_scene_change,
|
||||
_scene_update,
|
||||
};
|
||||
|
||||
Evas_3D_Scene *
|
||||
evas_3d_scene_new(Evas *e)
|
||||
{
|
||||
Evas_3D_Scene *scene = NULL;
|
||||
|
||||
scene = (Evas_3D_Scene *)calloc(1, sizeof(Evas_3D_Scene));
|
||||
|
||||
if (scene == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evas_3d_object_init(&scene->base, e, EVAS_3D_OBJECT_TYPE_SCENE, &scene_func);
|
||||
evas_color_set(&scene->bg_color, 0.0, 0.0, 0.0, 0.0);
|
||||
|
||||
return scene;
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Scene *
|
||||
evas_3d_scene_add(Evas *e)
|
||||
{
|
||||
return evas_3d_scene_new(e);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_scene_del(Evas_3D_Scene *scene)
|
||||
{
|
||||
evas_3d_object_unreference(&scene->base);
|
||||
}
|
||||
|
||||
EAPI Evas *
|
||||
evas_3d_scene_evas_get(const Evas_3D_Scene *scene)
|
||||
{
|
||||
return scene->base.evas;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_scene_root_node_set(Evas_3D_Scene *scene, Evas_3D_Node *node)
|
||||
{
|
||||
if (scene->root_node == node)
|
||||
return;
|
||||
|
||||
if (scene->root_node)
|
||||
{
|
||||
evas_3d_node_scene_root_del(scene->root_node, scene);
|
||||
evas_3d_object_unreference(&scene->root_node->base);
|
||||
}
|
||||
|
||||
scene->root_node = node;
|
||||
|
||||
if (node)
|
||||
{
|
||||
evas_3d_object_reference(&node->base);
|
||||
evas_3d_node_scene_root_add(node, scene);
|
||||
}
|
||||
|
||||
evas_3d_object_change(&scene->base, EVAS_3D_STATE_SCENE_ROOT_NODE, NULL);
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Node *
|
||||
evas_3d_scene_root_node_get(const Evas_3D_Scene *scene)
|
||||
{
|
||||
return scene->root_node;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_scene_camera_node_set(Evas_3D_Scene *scene, Evas_3D_Node *node)
|
||||
{
|
||||
if (scene->camera_node == node)
|
||||
return;
|
||||
|
||||
if (scene->camera_node)
|
||||
{
|
||||
evas_3d_node_scene_camera_del(scene->camera_node, scene);
|
||||
evas_3d_object_unreference(&scene->camera_node->base);
|
||||
}
|
||||
|
||||
scene->camera_node = node;
|
||||
|
||||
if (node)
|
||||
{
|
||||
evas_3d_object_reference(&node->base);
|
||||
evas_3d_node_scene_camera_add(node, scene);
|
||||
}
|
||||
|
||||
evas_3d_object_change(&scene->base, EVAS_3D_STATE_SCENE_CAMERA_NODE, NULL);
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Node *
|
||||
evas_3d_scene_camera_node_get(const Evas_3D_Scene *scene)
|
||||
{
|
||||
return scene->camera_node;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_scene_size_set(Evas_3D_Scene *scene, int w, int h)
|
||||
{
|
||||
scene->w = w;
|
||||
scene->h = h;
|
||||
evas_3d_object_change(&scene->base, EVAS_3D_STATE_SCENE_SIZE, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_scene_size_get(const Evas_3D_Scene *scene, int *w, int *h)
|
||||
{
|
||||
if (w) *w = scene->w;
|
||||
if (h) *h = scene->h;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_scene_background_color_set(Evas_3D_Scene *scene,
|
||||
Evas_Real r, Evas_Real g, Evas_Real b, Evas_Real a)
|
||||
{
|
||||
evas_color_set(&scene->bg_color, r, g, b, a);
|
||||
evas_3d_object_change(&scene->base, EVAS_3D_STATE_SCENE_BACKGROUND_COLOR, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_scene_background_color_get(const Evas_3D_Scene *scene,
|
||||
Evas_Real *r, Evas_Real *g, Evas_Real *b, Evas_Real *a)
|
||||
{
|
||||
if (r) *r = scene->bg_color.r;
|
||||
if (g) *g = scene->bg_color.g;
|
||||
if (b) *b = scene->bg_color.b;
|
||||
if (a) *a = scene->bg_color.a;
|
||||
}
|
||||
|
||||
static inline Eina_Bool
|
||||
_pick_data_triangle_add(Evas_3D_Pick_Data *data, const Evas_Ray3 *ray,
|
||||
const Evas_Triangle3 *tri)
|
||||
{
|
||||
Evas_Vec3 e1, e2, tvec, pvec, qvec;
|
||||
Evas_Real det, inv_det, u, v, t;
|
||||
|
||||
evas_vec3_subtract(&e1, &tri->p1, &tri->p0);
|
||||
evas_vec3_subtract(&e2, &tri->p2, &tri->p0);
|
||||
|
||||
evas_vec3_cross_product(&pvec, &ray->dir, &e2);
|
||||
det = evas_vec3_dot_product(&e1, &pvec);
|
||||
|
||||
/* If determinant is near zero, ray lies in plane of triangle. */
|
||||
if (det > -0.0000001 && det < 0.0000001)
|
||||
return EINA_FALSE;
|
||||
|
||||
inv_det = 1.0 / det;
|
||||
|
||||
/* Calculate distance from p0 to ray origin. */
|
||||
evas_vec3_subtract(&tvec, &ray->org, &tri->p0);
|
||||
|
||||
/* Calculate U parameter and test bounds. */
|
||||
u = evas_vec3_dot_product(&tvec, &pvec) * inv_det;
|
||||
|
||||
if (u < 0.0 || u > 1.0)
|
||||
return EINA_FALSE;
|
||||
|
||||
/* Prepare to tst V parameter. */
|
||||
evas_vec3_cross_product(&qvec, &tvec, &e1);
|
||||
|
||||
/* Calculate V parameter and test bounds. */
|
||||
v = evas_vec3_dot_product(&ray->dir, &qvec) * inv_det;
|
||||
|
||||
if (v < 0.0 || u + v > 1.0)
|
||||
return EINA_FALSE;
|
||||
|
||||
/* Calculate T parameter and test bounds. */
|
||||
t = evas_vec3_dot_product(&e2, &qvec) * inv_det;
|
||||
|
||||
if (t >= 0.0 && t <= 1.0)
|
||||
{
|
||||
if (!data->picked || t < data->z)
|
||||
{
|
||||
data->picked = EINA_TRUE;
|
||||
data->z = t;
|
||||
data->u = u;
|
||||
data->v = v;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_position_get(Evas_Vec3 *out, const Evas_3D_Vertex_Buffer *pos0, const Evas_3D_Vertex_Buffer *pos1,
|
||||
Evas_Real weight, int index)
|
||||
{
|
||||
if (pos1->data == NULL)
|
||||
{
|
||||
float *ptr = (float *)((char *)pos0->data + pos0->stride * index);
|
||||
|
||||
out->x = ptr[0];
|
||||
out->y = ptr[1];
|
||||
out->z = ptr[2];
|
||||
}
|
||||
else
|
||||
{
|
||||
float *ptr0, *ptr1;
|
||||
|
||||
ptr0 = (float *)((char *)pos0->data + pos0->stride * index);
|
||||
ptr1 = (float *)((char *)pos1->data + pos1->stride * index);
|
||||
|
||||
out->x = ptr0[0] * weight + ptr1[0] * (1.0 - weight);
|
||||
out->y = ptr0[1] * weight + ptr1[1] * (1.0 - weight);
|
||||
out->z = ptr0[2] * weight + ptr1[2] * (1.0 - weight);
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_pick_data_texcoord_update(Evas_3D_Pick_Data *data,
|
||||
const Evas_3D_Vertex_Buffer *tex0, const Evas_3D_Vertex_Buffer *tex1,
|
||||
Evas_Real weight, unsigned int i0, unsigned int i1, unsigned int i2)
|
||||
{
|
||||
Evas_Real s0, s1, s2;
|
||||
Evas_Real t0, t1, t2;
|
||||
|
||||
if (tex1->data == NULL)
|
||||
{
|
||||
float *ptr;
|
||||
|
||||
ptr = (float *)((char *)tex0->data + tex0->stride * i0);
|
||||
|
||||
s0 = ptr[0];
|
||||
t0 = ptr[1];
|
||||
|
||||
ptr = (float *)((char *)tex0->data + tex0->stride * i1);
|
||||
|
||||
s1 = ptr[0];
|
||||
t1 = ptr[1];
|
||||
|
||||
ptr = (float *)((char *)tex0->data + tex0->stride * i2);
|
||||
|
||||
s2 = ptr[0];
|
||||
t2 = ptr[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
float *ptr0, *ptr1;
|
||||
|
||||
ptr0 = (float *)((char *)tex0->data + tex0->stride * i0);
|
||||
ptr1 = (float *)((char *)tex1->data + tex1->stride * i0);
|
||||
|
||||
s0 = ptr0[0] * weight + ptr1[0] * (1.0 - weight);
|
||||
t0 = ptr0[1] * weight + ptr1[1] * (1.0 - weight);
|
||||
|
||||
ptr0 = (float *)((char *)tex0->data + tex0->stride * i1);
|
||||
ptr1 = (float *)((char *)tex1->data + tex1->stride * i1);
|
||||
|
||||
s1 = ptr0[0] * weight + ptr1[0] * (1.0 - weight);
|
||||
t1 = ptr0[1] * weight + ptr1[1] * (1.0 - weight);
|
||||
|
||||
ptr0 = (float *)((char *)tex0->data + tex0->stride * i2);
|
||||
ptr1 = (float *)((char *)tex1->data + tex1->stride * i2);
|
||||
|
||||
s2 = ptr0[0] * weight + ptr1[0] * (1.0 - weight);
|
||||
t2 = ptr0[1] * weight + ptr1[1] * (1.0 - weight);
|
||||
}
|
||||
|
||||
data->s = s0 * (1 - data->u - data->v) + s1 * data->u + s2 * data->v;
|
||||
data->t = t0 * (1 - data->u - data->v) + t1 * data->u + t2 * data->v;
|
||||
}
|
||||
|
||||
|
||||
static inline void
|
||||
_pick_data_mesh_add(Evas_3D_Pick_Data *data, const Evas_Ray3 *ray,
|
||||
Evas_3D_Mesh *mesh, int frame, Evas_3D_Node *node)
|
||||
{
|
||||
Evas_3D_Vertex_Buffer pos0, pos1, tex0, tex1;
|
||||
Evas_Real pos_weight, tex_weight;
|
||||
Evas_Triangle3 tri;
|
||||
int i;
|
||||
|
||||
memset(&pos0, 0x00, sizeof(Evas_3D_Vertex_Buffer));
|
||||
memset(&pos1, 0x00, sizeof(Evas_3D_Vertex_Buffer));
|
||||
memset(&tex0, 0x00, sizeof(Evas_3D_Vertex_Buffer));
|
||||
memset(&tex1, 0x00, sizeof(Evas_3D_Vertex_Buffer));
|
||||
|
||||
evas_3d_mesh_interpolate_vertex_buffer_get(mesh, frame, EVAS_3D_VERTEX_POSITION,
|
||||
&pos0, &pos1, &pos_weight);
|
||||
|
||||
evas_3d_mesh_interpolate_vertex_buffer_get(mesh, frame, EVAS_3D_VERTEX_TEXCOORD,
|
||||
&tex0, &tex1, &tex_weight);
|
||||
|
||||
if (mesh->indices)
|
||||
{
|
||||
unsigned int i0, i1, i2;
|
||||
|
||||
if (mesh->assembly == EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES)
|
||||
{
|
||||
for (i = 0; i < mesh->index_count; i += 3)
|
||||
{
|
||||
if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
{
|
||||
i0 = ((unsigned short *)mesh->indices)[i];
|
||||
i1 = ((unsigned short *)mesh->indices)[i + 1];
|
||||
i2 = ((unsigned short *)mesh->indices)[i + 2];
|
||||
}
|
||||
else
|
||||
{
|
||||
i0 = ((unsigned char *)mesh->indices)[i];
|
||||
i1 = ((unsigned char *)mesh->indices)[i + 1];
|
||||
i2 = ((unsigned char *)mesh->indices)[i + 2];
|
||||
}
|
||||
|
||||
_position_get(&tri.p0, &pos0, &pos1, pos_weight, i0);
|
||||
_position_get(&tri.p1, &pos0, &pos1, pos_weight, i1);
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i2);
|
||||
|
||||
if (_pick_data_triangle_add(data, ray, &tri))
|
||||
{
|
||||
_pick_data_texcoord_update(data, &tex0, &tex1, tex_weight, i0, i1, i2);
|
||||
data->mesh = mesh;
|
||||
data->node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mesh->assembly == EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_STRIP)
|
||||
{
|
||||
if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
{
|
||||
i1 = ((unsigned short *)mesh->indices)[0];
|
||||
i2 = ((unsigned short *)mesh->indices)[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
i1 = ((unsigned char *)mesh->indices)[0];
|
||||
i2 = ((unsigned char *)mesh->indices)[1];
|
||||
}
|
||||
|
||||
_position_get(&tri.p1, &pos0, &pos1, pos_weight, i1);
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i2);
|
||||
|
||||
for (i = 0; i < mesh->index_count - 2; i++)
|
||||
{
|
||||
tri.p0 = tri.p1;
|
||||
tri.p1 = tri.p2;
|
||||
|
||||
if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
i2 = ((unsigned short *)mesh->indices)[i + 2];
|
||||
else
|
||||
i2 = ((unsigned char *)mesh->indices)[i + 2];
|
||||
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i2);
|
||||
|
||||
if (_pick_data_triangle_add(data, ray, &tri))
|
||||
{
|
||||
if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
{
|
||||
i0 = ((unsigned short *)mesh->indices)[i];
|
||||
i1 = ((unsigned short *)mesh->indices)[i + 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
i0 = ((unsigned char *)mesh->indices)[i];
|
||||
i1 = ((unsigned char *)mesh->indices)[i + 1];
|
||||
}
|
||||
|
||||
_pick_data_texcoord_update(data, &tex0, &tex1, tex_weight, i0, i1, i2);
|
||||
data->mesh = mesh;
|
||||
data->node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mesh->assembly == EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_FAN)
|
||||
{
|
||||
if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
{
|
||||
i0 = ((unsigned short *)mesh->indices)[0];
|
||||
i2 = ((unsigned short *)mesh->indices)[1];
|
||||
}
|
||||
else
|
||||
{
|
||||
i0 = ((unsigned char *)mesh->indices)[0];
|
||||
i2 = ((unsigned char *)mesh->indices)[1];
|
||||
}
|
||||
|
||||
_position_get(&tri.p0, &pos0, &pos1, pos_weight, i0);
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i2);
|
||||
|
||||
for (i = 1; i < mesh->index_count - 1; i++)
|
||||
{
|
||||
tri.p1 = tri.p2;
|
||||
|
||||
if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
i2 = ((unsigned short *)mesh->indices)[i + 1];
|
||||
else
|
||||
i2 = ((unsigned char *)mesh->indices)[i + 1];
|
||||
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i2);
|
||||
|
||||
if (_pick_data_triangle_add(data, ray, &tri))
|
||||
{
|
||||
if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
i1 = ((unsigned short *)mesh->indices)[i];
|
||||
else
|
||||
i1 = ((unsigned char *)mesh->indices)[i];
|
||||
|
||||
_pick_data_texcoord_update(data, &tex0, &tex1, tex_weight, i0, i1, i2);
|
||||
data->mesh = mesh;
|
||||
data->node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mesh->index_format == EVAS_3D_INDEX_FORMAT_UNSIGNED_BYTE)
|
||||
{
|
||||
if (mesh->assembly == EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES)
|
||||
{
|
||||
for (i = 0; i < mesh->index_count; i += 3)
|
||||
{
|
||||
_position_get(&tri.p0, &pos0, &pos1, pos_weight, i);
|
||||
_position_get(&tri.p1, &pos0, &pos1, pos_weight, i + 1);
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i + 2);
|
||||
|
||||
if (_pick_data_triangle_add(data, ray, &tri))
|
||||
{
|
||||
_pick_data_texcoord_update(data, &tex0, &tex1, tex_weight, i, i + 1, i + 2);
|
||||
data->mesh = mesh;
|
||||
data->node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mesh->assembly == EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_STRIP)
|
||||
{
|
||||
_position_get(&tri.p1, &pos0, &pos1, pos_weight, 0);
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, 1);
|
||||
|
||||
for (i = 0; i < mesh->index_count - 2; i++)
|
||||
{
|
||||
tri.p0 = tri.p1;
|
||||
tri.p1 = tri.p2;
|
||||
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i + 2);
|
||||
|
||||
if (_pick_data_triangle_add(data, ray, &tri))
|
||||
{
|
||||
_pick_data_texcoord_update(data, &tex0, &tex1, tex_weight, i, i + 1, i + 2);
|
||||
data->mesh = mesh;
|
||||
data->node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (mesh->assembly == EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_FAN)
|
||||
{
|
||||
_position_get(&tri.p0, &pos0, &pos1, pos_weight, 0);
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, 1);
|
||||
|
||||
for (i = 1; i < mesh->index_count - 1; i++)
|
||||
{
|
||||
tri.p1 = tri.p2;
|
||||
|
||||
_position_get(&tri.p2, &pos0, &pos1, pos_weight, i + 1);
|
||||
|
||||
if (_pick_data_triangle_add(data, ray, &tri))
|
||||
{
|
||||
_pick_data_texcoord_update(data, &tex0, &tex1, tex_weight, 0, i, i + 1);
|
||||
data->mesh = mesh;
|
||||
data->node = node;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Eina_Bool
|
||||
_node_pick(Evas_3D_Node *node, void *data)
|
||||
{
|
||||
Evas_Ray3 ray;
|
||||
Evas_3D_Pick_Data *pick = (Evas_3D_Pick_Data *)data;
|
||||
Evas_Mat4 mvp;
|
||||
|
||||
if (! evas_box3_ray3_intersect(&node->aabb, &pick->ray_world))
|
||||
{
|
||||
/* Skip entire subtree. */
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
if (node->type == EVAS_3D_NODE_TYPE_MESH)
|
||||
{
|
||||
Eina_Iterator *itr;
|
||||
void *ptr;
|
||||
|
||||
/* Transform ray into local coordinate space. */
|
||||
evas_mat4_multiply(&mvp, &pick->matrix_vp, &node->data.mesh.matrix_local_to_world);
|
||||
evas_ray3_init(&ray, pick->x, pick->y, &mvp);
|
||||
|
||||
itr = eina_hash_iterator_data_new(node->data.mesh.node_meshes);
|
||||
|
||||
while (eina_iterator_next(itr, &ptr))
|
||||
{
|
||||
Evas_3D_Node_Mesh *nm = (Evas_3D_Node_Mesh *)ptr;
|
||||
_pick_data_mesh_add(pick, &ray, nm->mesh, nm->frame, node);
|
||||
}
|
||||
}
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
EAPI Eina_Bool
|
||||
evas_3d_scene_pick(const Evas_3D_Scene *scene, 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;
|
||||
|
||||
data.x = ((x * 2.0) / (Evas_Real)scene->w) - 1.0;
|
||||
data.y = (((scene->h - y - 1) * 2.0) / ((Evas_Real)scene->h)) - 1.0;
|
||||
|
||||
data.picked = EINA_FALSE;
|
||||
data.z = 1.0;
|
||||
data.node = NULL;
|
||||
data.mesh = NULL;
|
||||
data.s = 0.0;
|
||||
data.t = 0.0;
|
||||
|
||||
/* Update the scene graph. */
|
||||
evas_3d_object_update((Evas_3D_Object *)&scene->base);
|
||||
|
||||
evas_mat4_multiply(&data.matrix_vp,
|
||||
&scene->camera_node->data.camera.camera->projection,
|
||||
&scene->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(scene->root_node, EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER, EINA_TRUE,
|
||||
_node_pick, &data);
|
||||
|
||||
if (!data.picked)
|
||||
return EINA_FALSE;
|
||||
|
||||
if (s) *s = data.s;
|
||||
if (t) *t = data.t;
|
||||
if (node) *node = data.node;
|
||||
if (mesh) *mesh = data.mesh;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
|
@ -0,0 +1,440 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "evas_common_private.h"
|
||||
#include "evas_private.h"
|
||||
|
||||
static inline void
|
||||
_texture_proxy_set(Evas_3D_Texture *texture, Evas_Object *eo_src, Evas_Object_Protected_Data *src)
|
||||
{
|
||||
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, src->proxy, Evas_Object_Proxy_Data, proxy_src)
|
||||
{
|
||||
proxy_src->proxy_textures = eina_list_append(proxy_src->proxy_textures, texture);
|
||||
proxy_src->redraw = EINA_TRUE;
|
||||
}
|
||||
EINA_COW_WRITE_END(evas_object_proxy_cow, src->proxy, proxy_src);
|
||||
|
||||
texture->source = eo_src;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_texture_proxy_unset(Evas_3D_Texture *texture)
|
||||
{
|
||||
Evas_Object_Protected_Data *src = eo_data_scope_get(texture->source, EVAS_OBJ_CLASS);
|
||||
|
||||
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, src->proxy, Evas_Object_Proxy_Data, proxy_src);
|
||||
{
|
||||
proxy_src->proxy_textures = eina_list_remove(proxy_src->proxy_textures, texture);
|
||||
|
||||
if (eina_list_count(proxy_src->proxy_textures) == 0)
|
||||
{
|
||||
if (eina_list_count(proxy_src->proxies) == 0)
|
||||
{
|
||||
Evas_Public_Data *e = src->layer->evas;
|
||||
e->engine.func->image_map_surface_free(e->engine.data.output,
|
||||
proxy_src->surface);
|
||||
proxy_src->surface = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (proxy_src->src_invisible)
|
||||
{
|
||||
proxy_src->src_invisible = EINA_FALSE;
|
||||
src->changed_src_visible = EINA_TRUE;
|
||||
evas_object_change(texture->source, src);
|
||||
evas_object_smart_member_cache_invalidate(texture->source,
|
||||
EINA_FALSE, EINA_FALSE, EINA_TRUE);
|
||||
}
|
||||
}
|
||||
EINA_COW_WRITE_END(evas_object_proxy_cow, src->proxy, proxy_src);
|
||||
|
||||
texture->source = NULL;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_texture_proxy_subrender(Evas_3D_Texture *texture)
|
||||
{
|
||||
/* Code taken from _proxy_subrender() in file evas_object_image.c */
|
||||
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
Evas_Object_Protected_Data *source;
|
||||
void *ctx, *image;
|
||||
int w, h;
|
||||
Eina_Bool is_image;
|
||||
|
||||
if (!texture->source)
|
||||
return;
|
||||
|
||||
source = eo_data_scope_get(texture->source, EVAS_OBJ_CLASS);
|
||||
|
||||
is_image = eo_isa(texture->source, EVAS_OBJ_IMAGE_CLASS);
|
||||
|
||||
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy, Evas_Object_Proxy_Data, proxy_write)
|
||||
{
|
||||
proxy_write->redraw = EINA_FALSE;
|
||||
|
||||
if (is_image)
|
||||
{
|
||||
image = source->func->engine_data_get(texture->source);
|
||||
e->engine.func->image_size_get(e->engine.data.output, image, &w, &h);
|
||||
}
|
||||
else
|
||||
{
|
||||
w = source->cur->geometry.w;
|
||||
h = source->cur->geometry.h;
|
||||
}
|
||||
|
||||
/* We need to redraw surface then */
|
||||
if ((proxy_write->surface) &&
|
||||
((proxy_write->w != w) || (proxy_write->h != h)))
|
||||
{
|
||||
e->engine.func->image_map_surface_free(e->engine.data.output,
|
||||
proxy_write->surface);
|
||||
proxy_write->surface = NULL;
|
||||
}
|
||||
|
||||
/* FIXME: Hardcoded alpha 'on' */
|
||||
/* FIXME (cont): Should see if the object has alpha */
|
||||
if (!proxy_write->surface)
|
||||
{
|
||||
proxy_write->surface = e->engine.func->image_map_surface_new
|
||||
(e->engine.data.output, w, h, 1);
|
||||
if (!proxy_write->surface) goto end;
|
||||
proxy_write->w = w;
|
||||
proxy_write->h = h;
|
||||
}
|
||||
|
||||
ctx = e->engine.func->context_new(e->engine.data.output);
|
||||
e->engine.func->context_color_set(e->engine.data.output, ctx, 0, 0,
|
||||
0, 0);
|
||||
e->engine.func->context_render_op_set(e->engine.data.output, ctx,
|
||||
EVAS_RENDER_COPY);
|
||||
e->engine.func->rectangle_draw(e->engine.data.output, ctx,
|
||||
proxy_write->surface, 0, 0, w, h,
|
||||
EINA_FALSE);
|
||||
e->engine.func->context_free(e->engine.data.output, ctx);
|
||||
|
||||
ctx = e->engine.func->context_new(e->engine.data.output);
|
||||
|
||||
if (is_image)
|
||||
{
|
||||
void *image = source->func->engine_data_get(texture->source);
|
||||
|
||||
if (image)
|
||||
{
|
||||
int imagew, imageh;
|
||||
e->engine.func->image_size_get(e->engine.data.output, image,
|
||||
&imagew, &imageh);
|
||||
e->engine.func->image_draw(e->engine.data.output, ctx,
|
||||
proxy_write->surface, image,
|
||||
0, 0, imagew, imageh, 0, 0, w, h, 0, EINA_FALSE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
evas_render_mapped(e, texture->source, source, ctx, proxy_write->surface,
|
||||
-source->cur->geometry.x,
|
||||
-source->cur->geometry.y,
|
||||
1, 0, 0, e->output.w, e->output.h,
|
||||
NULL
|
||||
#ifdef REND_DBG
|
||||
, 1
|
||||
#endif
|
||||
, EINA_FALSE);
|
||||
}
|
||||
|
||||
e->engine.func->context_free(e->engine.data.output, ctx);
|
||||
proxy_write->surface = e->engine.func->image_dirty_region
|
||||
(e->engine.data.output, proxy_write->surface, 0, 0, w, h);
|
||||
}
|
||||
end:
|
||||
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write);
|
||||
}
|
||||
|
||||
static void
|
||||
_texture_fini(Evas_3D_Texture *texture)
|
||||
{
|
||||
if (texture->engine_data)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
e->engine.func->texture_free(e->engine.data.output, texture->engine_data);
|
||||
texture->engine_data = NULL;
|
||||
}
|
||||
|
||||
if (texture->materials)
|
||||
{
|
||||
eina_hash_free(texture->materials);
|
||||
texture->materials = NULL;
|
||||
}
|
||||
|
||||
if (texture->source)
|
||||
{
|
||||
_texture_proxy_unset(texture);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
_texture_free(Evas_3D_Object *obj)
|
||||
{
|
||||
Evas_3D_Texture *texture = (Evas_3D_Texture *)obj;
|
||||
|
||||
_texture_fini(texture);
|
||||
free(texture);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
_texture_material_change_notify(const Eina_Hash *hash EINA_UNUSED, const void *key,
|
||||
void *data EINA_UNUSED, void *fdata)
|
||||
{
|
||||
Evas_3D_Material *m = *(Evas_3D_Material **)key;
|
||||
evas_3d_object_change(&m->base, EVAS_3D_STATE_MATERIAL_TEXTURE, (Evas_3D_Object *)fdata);
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
_texture_change(Evas_3D_Object *obj, Evas_3D_State state EINA_UNUSED,
|
||||
Evas_3D_Object *ref EINA_UNUSED)
|
||||
{
|
||||
Evas_3D_Texture *texture = (Evas_3D_Texture *)obj;
|
||||
|
||||
if (texture->materials)
|
||||
eina_hash_foreach(texture->materials, _texture_material_change_notify, obj);
|
||||
}
|
||||
|
||||
static void
|
||||
_texture_update(Evas_3D_Object *obj)
|
||||
{
|
||||
Evas_3D_Texture *texture = (Evas_3D_Texture *)obj;
|
||||
|
||||
if (texture->source)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
Evas_Object_Protected_Data *src = eo_data_scope_get(texture->source, EVAS_OBJ_CLASS);
|
||||
|
||||
if (texture->engine_data == NULL)
|
||||
{
|
||||
texture->engine_data = e->engine.func->texture_new(e->engine.data.output);
|
||||
|
||||
if (texture->engine_data == NULL)
|
||||
{
|
||||
ERR("Failed to create engine-side texture object.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (src->proxy->surface && !src->proxy->redraw)
|
||||
{
|
||||
e->engine.func->texture_image_set(e->engine.data.output, texture->engine_data,
|
||||
src->proxy->surface);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
texture->proxy_rendering = EINA_TRUE;
|
||||
_texture_proxy_subrender(texture);
|
||||
|
||||
e->engine.func->texture_image_set(e->engine.data.output, texture->engine_data,
|
||||
src->proxy->surface);
|
||||
texture->proxy_rendering = EINA_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static const Evas_3D_Object_Func texture_func =
|
||||
{
|
||||
_texture_free,
|
||||
_texture_change,
|
||||
_texture_update,
|
||||
};
|
||||
|
||||
void
|
||||
evas_3d_texture_material_add(Evas_3D_Texture *texture, Evas_3D_Material *material)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (texture->materials == NULL)
|
||||
{
|
||||
texture->materials = eina_hash_pointer_new(NULL);
|
||||
|
||||
if (texture->materials == NULL)
|
||||
{
|
||||
ERR("Failed to create hash table.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
count = (int)eina_hash_find(texture->materials, &material);
|
||||
|
||||
/* Increase reference count or add new one if not exist. */
|
||||
eina_hash_set(texture->materials, &material, (const void *)(count + 1));
|
||||
}
|
||||
|
||||
void
|
||||
evas_3d_texture_material_del(Evas_3D_Texture *texture, Evas_3D_Material *material)
|
||||
{
|
||||
int count = 0;
|
||||
|
||||
if (texture->materials == NULL)
|
||||
{
|
||||
ERR("No material to delete.");
|
||||
return;
|
||||
}
|
||||
|
||||
count = (int)eina_hash_find(texture->materials, &material);
|
||||
|
||||
if (count == 1)
|
||||
eina_hash_del(texture->materials, &material, NULL);
|
||||
else
|
||||
eina_hash_set(texture->materials, &material, (const void *)(count - 1));
|
||||
}
|
||||
|
||||
Evas_3D_Texture *
|
||||
evas_3d_texture_new(Evas *e)
|
||||
{
|
||||
Evas_3D_Texture *texture = NULL;
|
||||
|
||||
texture = (Evas_3D_Texture *)calloc(1, sizeof(Evas_3D_Texture));
|
||||
|
||||
if (texture == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
evas_3d_object_init(&texture->base, e, EVAS_3D_OBJECT_TYPE_TEXTURE, &texture_func);
|
||||
return texture;
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Texture *
|
||||
evas_3d_texture_add(Evas *e)
|
||||
{
|
||||
return evas_3d_texture_new(e);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_del(Evas_3D_Texture *texture)
|
||||
{
|
||||
evas_3d_object_unreference(&texture->base);
|
||||
}
|
||||
|
||||
EAPI Evas *
|
||||
evas_3d_texture_evas_get(const Evas_3D_Texture *texture)
|
||||
{
|
||||
return texture->base.evas;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_data_set(Evas_3D_Texture *texture, Evas_3D_Color_Format color_format,
|
||||
Evas_3D_Pixel_Format pixel_format, int w, int h, const void *data)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
|
||||
if (texture->engine_data == NULL)
|
||||
texture->engine_data = e->engine.func->texture_new(e->engine.data.output);
|
||||
|
||||
e->engine.func->texture_data_set(e->engine.data.output, texture->engine_data,
|
||||
color_format, pixel_format, w, h, data);
|
||||
|
||||
evas_3d_object_change(&texture->base, EVAS_3D_STATE_TEXTURE_DATA, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_file_set(Evas_3D_Texture *texture, const char *file, const char *key)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
|
||||
if (texture->engine_data == NULL)
|
||||
texture->engine_data = e->engine.func->texture_new(e->engine.data.output);
|
||||
|
||||
e->engine.func->texture_file_set(e->engine.data.output, texture->engine_data, file, key);
|
||||
evas_3d_object_change(&texture->base, EVAS_3D_STATE_TEXTURE_DATA, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_source_set(Evas_3D_Texture *texture, Evas_Object *source)
|
||||
{
|
||||
Evas_Object_Protected_Data *src;
|
||||
|
||||
if (source == texture->source)
|
||||
return;
|
||||
|
||||
_texture_fini(texture);
|
||||
|
||||
if (source == NULL)
|
||||
return;
|
||||
|
||||
if (evas_object_evas_get(source) != texture->base.evas)
|
||||
{
|
||||
ERR("Not matching canvas.");
|
||||
return;
|
||||
}
|
||||
|
||||
src = eo_data_scope_get(source, EVAS_OBJ_CLASS);
|
||||
|
||||
if (src->delete_me)
|
||||
{
|
||||
ERR("Source object is deleted.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (src->layer == NULL)
|
||||
{
|
||||
ERR("No evas surface associated with the source object.");
|
||||
return;
|
||||
}
|
||||
|
||||
_texture_proxy_set(texture, source, src);
|
||||
evas_3d_object_change(&texture->base, EVAS_3D_STATE_TEXTURE_DATA, NULL);
|
||||
}
|
||||
|
||||
EAPI Evas_3D_Color_Format
|
||||
evas_3d_texture_color_format_get(const Evas_3D_Texture *texture)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
Evas_3D_Color_Format format;
|
||||
|
||||
e->engine.func->texture_color_format_get(e->engine.data.output, texture->engine_data, &format);
|
||||
return format;
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_size_get(const Evas_3D_Texture *texture, int *w, int *h)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
e->engine.func->texture_size_get(e->engine.data.output, texture->engine_data, w, h);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_wrap_set(Evas_3D_Texture *texture,
|
||||
Evas_3D_Wrap_Mode s, Evas_3D_Wrap_Mode t)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
e->engine.func->texture_wrap_set(e->engine.data.output, texture->engine_data, s, t);
|
||||
evas_3d_object_change(&texture->base, EVAS_3D_STATE_TEXTURE_WRAP, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_wrap_get(const Evas_3D_Texture *texture,
|
||||
Evas_3D_Wrap_Mode *s, Evas_3D_Wrap_Mode *t)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
e->engine.func->texture_wrap_get(e->engine.data.output, texture->engine_data, s, t);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_filter_set(Evas_3D_Texture *texture,
|
||||
Evas_3D_Texture_Filter min, Evas_3D_Texture_Filter mag)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
e->engine.func->texture_filter_set(e->engine.data.output, texture->engine_data, min, mag);
|
||||
evas_3d_object_change(&texture->base, EVAS_3D_STATE_TEXTURE_FILTER, NULL);
|
||||
}
|
||||
|
||||
EAPI void
|
||||
evas_3d_texture_filter_get(const Evas_3D_Texture *texture,
|
||||
Evas_3D_Texture_Filter *min, Evas_3D_Texture_Filter *mag)
|
||||
{
|
||||
Evas_Public_Data *e = eo_data_scope_get(texture->base.evas, EVAS_CLASS);
|
||||
e->engine.func->texture_filter_get(e->engine.data.output, texture->engine_data, min, mag);
|
||||
}
|
|
@ -27,6 +27,7 @@ class Evas_Image (Evas_Object)
|
|||
double dpi; /*@ The new DPI resolution. */
|
||||
}
|
||||
}
|
||||
|
||||
source_clip {
|
||||
set {
|
||||
/*@
|
||||
|
@ -996,6 +997,32 @@ class Evas_Image (Evas_Object)
|
|||
return int;
|
||||
}
|
||||
}
|
||||
|
||||
t3d_scene {
|
||||
set {
|
||||
/*
|
||||
@def evas_obj_image_3d_scene_set
|
||||
@since 1.8
|
||||
|
||||
Set the 3D scene on an image object.
|
||||
|
||||
@see evas_object_image_3d_scene_set
|
||||
*/
|
||||
}
|
||||
get {
|
||||
/*
|
||||
@def evas_obj_image_3d_scene_get
|
||||
@since 1.8
|
||||
|
||||
Get the 3D scene on an image object.
|
||||
|
||||
@see evas_object_image_3d_scene_get
|
||||
*/
|
||||
}
|
||||
values {
|
||||
Evas_3D_Scene *scene; /*@ 3D scene on an image object. */
|
||||
}
|
||||
}
|
||||
}
|
||||
methods {
|
||||
preload_begin {
|
||||
|
|
|
@ -79,6 +79,8 @@ struct _Evas_Object_Image_State
|
|||
|
||||
Evas_Object *source;
|
||||
Evas_Map *defmap;
|
||||
Evas_3D_Scene *scene;
|
||||
|
||||
union {
|
||||
const char *file;
|
||||
Eina_File *f;
|
||||
|
@ -184,6 +186,9 @@ static void _proxy_unset(Evas_Object *proxy, Evas_Object_Protected_Data *obj, Ev
|
|||
static void _proxy_set(Evas_Object *proxy, Evas_Object *src);
|
||||
static void _proxy_error(Evas_Object *proxy, void *context, void *output, void *surface, int x, int y, Eina_Bool do_async);
|
||||
|
||||
static void _3d_set(Evas_Object *eo_obj, Evas_3D_Scene *scene);
|
||||
static void _3d_unset(Evas_Object *eo_obj, Evas_Object_Protected_Data *image, Evas_Image_Data *o);
|
||||
|
||||
static const Evas_Object_Func object_func =
|
||||
{
|
||||
/* methods (compulsory) */
|
||||
|
@ -283,6 +288,7 @@ _evas_object_image_cleanup(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
eo_obj);
|
||||
}
|
||||
if (o->cur->source) _proxy_unset(eo_obj, obj, o);
|
||||
if (o->cur->scene) _3d_unset(eo_obj, obj, o);
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
|
@ -400,6 +406,8 @@ _image_init_set(const Eina_File *f, const char *file, const char *key,
|
|||
{
|
||||
if (o->cur->source) _proxy_unset(eo_obj, obj, o);
|
||||
|
||||
if (o->cur->scene) _3d_unset(eo_obj, obj, o);
|
||||
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||
{
|
||||
if (f)
|
||||
|
@ -763,6 +771,30 @@ _evas_image_source_visible_get(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o)
|
|||
return visible;
|
||||
}
|
||||
|
||||
|
||||
EOLIAN static void
|
||||
_evas_image_t3d_scene_set(Eo *eo_obj, Evas_Image_Data *o, Evas_3D_Scene *scene)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
|
||||
|
||||
if (o->cur->scene == scene)
|
||||
return;
|
||||
|
||||
_evas_object_image_cleanup(eo_obj, obj, o);
|
||||
|
||||
if (o->cur->u.file || o->cur->key)
|
||||
evas_object_image_file_set(eo_obj, NULL, NULL);
|
||||
|
||||
if (scene) _3d_set(eo_obj, scene);
|
||||
else _3d_unset(eo_obj, obj, o);
|
||||
}
|
||||
|
||||
EOLIAN static Evas_3D_Scene *
|
||||
_evas_image_t3d_scene_get(Eo *eo_obj EINA_UNUSED, Evas_Image_Data *o)
|
||||
{
|
||||
return o->cur->scene;
|
||||
}
|
||||
|
||||
EOLIAN static void
|
||||
_evas_image_border_set(Eo *eo_obj, Evas_Image_Data *o, int l, int r, int t, int b)
|
||||
{
|
||||
|
@ -2384,6 +2416,145 @@ _proxy_subrender(Evas *eo_e, Evas_Object *eo_source, Evas_Object *eo_proxy, Evas
|
|||
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write);
|
||||
}
|
||||
|
||||
static void
|
||||
_3d_set(Evas_Object *eo_obj, Evas_3D_Scene *scene)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
|
||||
Evas_Image_Data *o = eo_data_scope_get(eo_obj, MY_CLASS);
|
||||
|
||||
evas_object_image_file_set(eo_obj, NULL, NULL);
|
||||
|
||||
EINA_COW_WRITE_BEGIN(evas_object_3d_cow, obj->data_3d, Evas_Object_3D_Data, data)
|
||||
{
|
||||
data->surface = NULL;
|
||||
data->w = 0;
|
||||
data->h = 0;
|
||||
evas_3d_object_reference(&scene->base);
|
||||
}
|
||||
EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data);
|
||||
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||
{
|
||||
state_write->scene = scene;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||
|
||||
scene->images = eina_list_append(scene->images, eo_obj);
|
||||
}
|
||||
|
||||
static void
|
||||
_3d_unset(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
|
||||
{
|
||||
if (!o->cur->scene) return;
|
||||
|
||||
if (o->cur->scene)
|
||||
{
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||
o->cur->scene->images = eina_list_remove(o->cur->scene->images, eo_obj);
|
||||
evas_3d_object_unreference(&state_write->scene->base);
|
||||
state_write->scene = NULL;
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||
}
|
||||
|
||||
if (o->cur->defmap)
|
||||
{
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||
{
|
||||
evas_map_free(state_write->defmap);
|
||||
state_write->defmap = NULL;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||
}
|
||||
|
||||
EINA_COW_WRITE_BEGIN(evas_object_3d_cow, obj->data_3d, Evas_Object_3D_Data, data)
|
||||
{
|
||||
if (data->surface)
|
||||
{
|
||||
obj->layer->evas->engine.func->image_free(obj->layer->evas->engine.data.output,
|
||||
data->surface);
|
||||
}
|
||||
|
||||
data->surface = NULL;
|
||||
data->w = 0;
|
||||
data->h = 0;
|
||||
}
|
||||
EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data);
|
||||
|
||||
}
|
||||
|
||||
static void
|
||||
_3d_render(Evas *eo_e, Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj, Evas_Image_Data *o EINA_UNUSED, Evas_3D_Scene *scene)
|
||||
{
|
||||
Evas_Public_Data *e;
|
||||
Eina_Bool need_native_set = EINA_FALSE;
|
||||
Evas_3D_Scene_Data scene_data;
|
||||
|
||||
if (scene == NULL)
|
||||
return;
|
||||
|
||||
if((scene->w == 0) || (scene->h == 0))
|
||||
return;
|
||||
|
||||
e = eo_data_scope_get(eo_e, EVAS_CLASS);
|
||||
|
||||
if (scene->surface != NULL)
|
||||
{
|
||||
int w, h;
|
||||
|
||||
e->engine.func->drawable_size_get(e->engine.data.output, scene->surface, &w, &h);
|
||||
|
||||
if ((w != scene->w) || (h != scene->h))
|
||||
{
|
||||
e->engine.func->drawable_free(e->engine.data.output, scene->surface);
|
||||
scene->surface = NULL;
|
||||
need_native_set = EINA_TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (scene->surface == NULL)
|
||||
{
|
||||
/* TODO: Hard-coded alpha on. */
|
||||
scene->surface = e->engine.func->drawable_new(e->engine.data.output,
|
||||
scene->w, scene->h, 1);
|
||||
need_native_set = EINA_TRUE;
|
||||
}
|
||||
|
||||
EINA_COW_WRITE_BEGIN(evas_object_3d_cow, obj->data_3d, Evas_Object_3D_Data, data)
|
||||
{
|
||||
if (need_native_set)
|
||||
{
|
||||
data->surface = e->engine.func->image_drawable_set(e->engine.data.output,
|
||||
data->surface, scene->surface);
|
||||
}
|
||||
|
||||
data->w = scene->w;
|
||||
data->h = scene->h;
|
||||
}
|
||||
EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data);
|
||||
|
||||
evas_3d_scene_data_init(&scene_data);
|
||||
|
||||
scene_data.bg_color = scene->bg_color;
|
||||
scene_data.camera_node = scene->camera_node;
|
||||
|
||||
/* Phase 1 - Update scene graph tree. */
|
||||
evas_3d_object_update(&scene->base);
|
||||
|
||||
/* Phase 2 - Do frustum culling and get visible model nodes. */
|
||||
evas_3d_node_tree_traverse(scene->root_node, EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER, EINA_TRUE,
|
||||
evas_3d_node_mesh_collect, &scene_data);
|
||||
|
||||
/* Phase 3 - Collect active light nodes in the scene graph tree. */
|
||||
evas_3d_node_tree_traverse(scene->root_node, EVAS_3D_TREE_TRAVERSE_ANY_ORDER, EINA_FALSE,
|
||||
evas_3d_node_light_collect, &scene_data);
|
||||
|
||||
/* Phase 5 - Draw the scene. */
|
||||
e->engine.func->drawable_scene_render(e->engine.data.output, scene->surface, &scene_data);
|
||||
|
||||
/* Clean up temporary resources. */
|
||||
evas_3d_scene_data_fini(&scene_data);
|
||||
}
|
||||
|
||||
static void
|
||||
evas_object_image_unload(Evas_Object *eo_obj, Eina_Bool dirty)
|
||||
{
|
||||
|
@ -2608,6 +2779,7 @@ evas_object_image_free(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
|
|||
}
|
||||
if (o->cur->key) eina_stringshare_del(o->cur->key);
|
||||
if (o->cur->source) _proxy_unset(eo_obj, obj, o);
|
||||
if (o->cur->scene) _3d_unset(eo_obj, obj, o);
|
||||
if (obj->layer && obj->layer->evas)
|
||||
{
|
||||
if (o->engine_data)
|
||||
|
@ -2857,7 +3029,17 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
|||
(o->cur->source ?
|
||||
eo_data_scope_get(o->cur->source, EVAS_OBJ_CLASS):
|
||||
NULL);
|
||||
if (!o->cur->source)
|
||||
|
||||
if (o->cur->scene)
|
||||
{
|
||||
_3d_render(obj->layer->evas->evas, eo_obj, obj, o, o->cur->scene);
|
||||
pixels = obj->data_3d->surface;
|
||||
imagew = obj->data_3d->w;
|
||||
imageh = obj->data_3d->h;
|
||||
uvw = imagew;
|
||||
uvh = imageh;
|
||||
}
|
||||
else if (!o->cur->source)
|
||||
{
|
||||
pixels = evas_process_dirty_pixels(eo_obj, obj, o, output, o->engine_data);
|
||||
/* pixels = o->engine_data; */
|
||||
|
@ -3186,6 +3368,16 @@ evas_object_image_render_pre(Evas_Object *eo_obj,
|
|||
goto done;
|
||||
}
|
||||
}
|
||||
else if (o->cur->scene)
|
||||
{
|
||||
Evas_3D_Scene *scene = o->cur->scene;
|
||||
|
||||
if (evas_3d_object_dirty_get(&scene->base, EVAS_3D_STATE_ANY))
|
||||
{
|
||||
evas_object_render_pre_prev_cur_add(&e->clip_changes, eo_obj, obj);
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
/* now figure what changed and add draw rects */
|
||||
/* if it just became visible or invisible */
|
||||
|
|
|
@ -23,7 +23,7 @@ get_layer_objects(Evas_Layer *l)
|
|||
|
||||
/* evas internal stuff */
|
||||
static const Evas_Object_Proxy_Data default_proxy = {
|
||||
NULL, NULL, 0, 0, NULL, 0, 0, 0, 0
|
||||
NULL, NULL, NULL, 0, 0, NULL, 0, 0, 0, 0
|
||||
};
|
||||
static const Evas_Object_Map_Data default_map = {
|
||||
{ NULL, NULL, 0, 0 }, { NULL, NULL, 0, 0 }, NULL, 0, 0, NULL, NULL
|
||||
|
@ -39,16 +39,20 @@ Eina_Cow *evas_object_proxy_cow = NULL;
|
|||
Eina_Cow *evas_object_map_cow = NULL;
|
||||
Eina_Cow *evas_object_state_cow = NULL;
|
||||
|
||||
Eina_Cow *evas_object_3d_cow = NULL;
|
||||
|
||||
static Eina_Bool
|
||||
_init_cow(void)
|
||||
{
|
||||
if (evas_object_map_cow && evas_object_proxy_cow && evas_object_state_cow) return EINA_TRUE;
|
||||
if (evas_object_map_cow && evas_object_proxy_cow && evas_object_state_cow && evas_object_3d_cow) return EINA_TRUE;
|
||||
|
||||
evas_object_proxy_cow = eina_cow_add("Evas Object Proxy", sizeof (Evas_Object_Proxy_Data), 8, &default_proxy, EINA_TRUE);
|
||||
evas_object_map_cow = eina_cow_add("Evas Object Map", sizeof (Evas_Object_Map_Data), 8, &default_map, EINA_TRUE);
|
||||
evas_object_state_cow = eina_cow_add("Evas Object State", sizeof (Evas_Object_Protected_State), 64, &default_state, EINA_FALSE);
|
||||
|
||||
if (!(evas_object_map_cow && evas_object_proxy_cow && evas_object_state_cow))
|
||||
evas_object_3d_cow = eina_cow_add("Evas Object 3D", sizeof (Evas_Object_3D_Data), 8, &default_proxy, EINA_TRUE);
|
||||
|
||||
if (!(evas_object_map_cow && evas_object_proxy_cow && evas_object_state_cow && evas_object_3d_cow))
|
||||
{
|
||||
eina_cow_del(evas_object_proxy_cow);
|
||||
eina_cow_del(evas_object_map_cow);
|
||||
|
@ -56,6 +60,10 @@ _init_cow(void)
|
|||
evas_object_proxy_cow = NULL;
|
||||
evas_object_map_cow = NULL;
|
||||
evas_object_state_cow = NULL;
|
||||
|
||||
eina_cow_del(evas_object_3d_cow);
|
||||
evas_object_3d_cow = NULL;
|
||||
|
||||
return EINA_FALSE;
|
||||
}
|
||||
|
||||
|
@ -81,6 +89,7 @@ _evas_object_eo_base_constructor(Eo *eo_obj, Evas_Object_Protected_Data *obj)
|
|||
obj->map = eina_cow_alloc(evas_object_map_cow);
|
||||
obj->cur = eina_cow_alloc(evas_object_state_cow);
|
||||
obj->prev = eina_cow_alloc(evas_object_state_cow);
|
||||
obj->data_3d = eina_cow_alloc(evas_object_3d_cow);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -188,6 +197,7 @@ evas_object_free(Evas_Object *eo_obj, int clean_layer)
|
|||
eina_cow_free(evas_object_map_cow, (const Eina_Cow_Data**) &obj->map);
|
||||
eina_cow_free(evas_object_state_cow, (const Eina_Cow_Data**) &obj->cur);
|
||||
eina_cow_free(evas_object_state_cow, (const Eina_Cow_Data**) &obj->prev);
|
||||
eina_cow_free(evas_object_3d_cow, (const Eina_Cow_Data**) &obj->data_3d);
|
||||
eo_data_unref(eo_obj, obj->private_data);
|
||||
obj->private_data = NULL;
|
||||
|
||||
|
@ -204,6 +214,7 @@ evas_object_change(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
|
|||
Evas_Object_Protected_Data *obj2;
|
||||
Evas_Object *eo_obj2;
|
||||
Eina_Bool movch = EINA_FALSE;
|
||||
Evas_3D_Texture *texture;
|
||||
|
||||
if (!obj->layer) return;
|
||||
if (obj->layer->evas->nochange) return;
|
||||
|
@ -233,6 +244,10 @@ evas_object_change(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj)
|
|||
if (!obj2) continue;
|
||||
evas_object_change(eo_obj2, obj2);
|
||||
}
|
||||
EINA_LIST_FOREACH(obj->proxy->proxy_textures, l, texture)
|
||||
{
|
||||
evas_3d_object_change(&texture->base, EVAS_3D_STATE_TEXTURE_DATA, NULL);
|
||||
}
|
||||
if (obj->smart.parent)
|
||||
{
|
||||
Evas_Object_Protected_Data *smart_parent = eo_data_scope_get(obj->smart.parent, MY_CLASS);
|
||||
|
|
|
@ -0,0 +1,377 @@
|
|||
#ifndef EVAS_PRIVATE_H
|
||||
# error You shall not include this header directly
|
||||
#endif
|
||||
|
||||
#include "Evas_3D.h"
|
||||
#include "evas_3d_utils.h"
|
||||
|
||||
#define EVAS_3D_VERTEX_ATTRIB_COUNT 5
|
||||
#define EVAS_3D_MATERIAL_ATTRIB_COUNT 5
|
||||
|
||||
typedef struct _Evas_3D_Object Evas_3D_Object;
|
||||
typedef struct _Evas_3D_Scene_Data Evas_3D_Scene_Data;
|
||||
typedef struct _Evas_3D_Vertex_Buffer Evas_3D_Vertex_Buffer;
|
||||
typedef struct _Evas_3D_Mesh_Frame Evas_3D_Mesh_Frame;
|
||||
typedef struct _Evas_3D_Node_Mesh Evas_3D_Node_Mesh;
|
||||
typedef struct _Evas_3D_Object_Func Evas_3D_Object_Func;
|
||||
typedef struct _Evas_3D_Pick_Data Evas_3D_Pick_Data;
|
||||
typedef struct _Evas_3D_Interpolate_Vertex_Buffer Evas_3D_Interpolate_Vertex_Buffer;
|
||||
|
||||
typedef Eina_Bool (*Evas_3D_Node_Func)(Evas_3D_Node *, void *data);
|
||||
|
||||
typedef enum _Evas_3D_Object_Type
|
||||
{
|
||||
EVAS_3D_OBJECT_TYPE_INVALID = 0,
|
||||
EVAS_3D_OBJECT_TYPE_SCENE,
|
||||
EVAS_3D_OBJECT_TYPE_NODE,
|
||||
EVAS_3D_OBJECT_TYPE_CAMERA,
|
||||
EVAS_3D_OBJECT_TYPE_LIGHT,
|
||||
EVAS_3D_OBJECT_TYPE_MODEL,
|
||||
EVAS_3D_OBJECT_TYPE_MESH,
|
||||
EVAS_3D_OBJECT_TYPE_TEXTURE,
|
||||
EVAS_3D_OBJECT_TYPE_MATERIAL,
|
||||
} Evas_3D_Object_Type;
|
||||
|
||||
typedef enum _Evas_3D_State
|
||||
{
|
||||
EVAS_3D_STATE_MAX = 16,
|
||||
|
||||
EVAS_3D_STATE_ANY = 0,
|
||||
|
||||
EVAS_3D_STATE_SCENE_ROOT_NODE = 1,
|
||||
EVAS_3D_STATE_SCENE_CAMERA_NODE,
|
||||
EVAS_3D_STATE_SCENE_BACKGROUND_COLOR,
|
||||
EVAS_3D_STATE_SCENE_SIZE,
|
||||
|
||||
EVAS_3D_STATE_TEXTURE_DATA = 1,
|
||||
EVAS_3D_STATE_TEXTURE_WRAP,
|
||||
EVAS_3D_STATE_TEXTURE_FILTER,
|
||||
|
||||
EVAS_3D_STATE_MATERIAL_ID = 1,
|
||||
EVAS_3D_STATE_MATERIAL_COLOR,
|
||||
EVAS_3D_STATE_MATERIAL_TEXTURE,
|
||||
|
||||
EVAS_3D_STATE_MESH_VERTEX_COUNT = 1,
|
||||
EVAS_3D_STATE_MESH_FRAME,
|
||||
EVAS_3D_STATE_MESH_MATERIAL,
|
||||
EVAS_3D_STATE_MESH_TRANSFORM,
|
||||
EVAS_3D_STATE_MESH_VERTEX_DATA,
|
||||
EVAS_3D_STATE_MESH_INDEX_DATA,
|
||||
EVAS_3D_STATE_MESH_VERTEX_ASSEMBLY,
|
||||
EVAS_3D_STATE_MESH_SHADE_MODE,
|
||||
|
||||
EVAS_3D_STATE_CAMERA_PROJECTION = 1,
|
||||
|
||||
EVAS_3D_STATE_LIGHT_AMBIENT = 1,
|
||||
EVAS_3D_STATE_LIGHT_DIFFUSE,
|
||||
EVAS_3D_STATE_LIGHT_SPECULAR,
|
||||
EVAS_3D_STATE_LIGHT_SPOT_DIR,
|
||||
EVAS_3D_STATE_LIGHT_SPOT_EXP,
|
||||
EVAS_3D_STATE_LIGHT_SPOT_CUTOFF,
|
||||
EVAS_3D_STATE_LIGHT_ATTENUATION,
|
||||
|
||||
EVAS_3D_STATE_NODE_TRANSFORM = 1,
|
||||
EVAS_3D_STATE_NODE_MESH_GEOMETRY,
|
||||
EVAS_3D_STATE_NODE_MESH_MATERIAL,
|
||||
EVAS_3D_STATE_NODE_MESH_FRAME,
|
||||
EVAS_3D_STATE_NODE_MESH_SHADE_MODE,
|
||||
EVAS_3D_STATE_NODE_MESH_MATERIAL_ID,
|
||||
EVAS_3D_STATE_NODE_LIGHT,
|
||||
EVAS_3D_STATE_NODE_CAMERA,
|
||||
EVAS_3D_STATE_NODE_PARENT,
|
||||
EVAS_3D_STATE_NODE_MEMBER,
|
||||
} Evas_3D_State;
|
||||
|
||||
typedef enum _Evas_3D_Node_Traverse_Type
|
||||
{
|
||||
EVAS_3D_NODE_TRAVERSE_DOWNWARD,
|
||||
EVAS_3D_NODE_TRAVERSE_UPWARD,
|
||||
} Evas_3D_Node_Traverse_Type;
|
||||
|
||||
typedef enum _Evas_3D_Tree_Traverse_Type
|
||||
{
|
||||
EVAS_3D_TREE_TRAVERSE_PRE_ORDER,
|
||||
EVAS_3D_TREE_TRAVERSE_ANY_ORDER = EVAS_3D_TREE_TRAVERSE_PRE_ORDER,
|
||||
EVAS_3D_TREE_TRAVERSE_POST_ORDER,
|
||||
EVAS_3D_TREE_TRAVERSE_LEVEL_ORDER,
|
||||
} Evas_3D_Tree_Traverse_Type;
|
||||
|
||||
struct _Evas_3D_Object_Func
|
||||
{
|
||||
void (*free)(Evas_3D_Object *obj);
|
||||
void (*change)(Evas_3D_Object *obj, Evas_3D_State state, Evas_3D_Object *ref);
|
||||
void (*update)(Evas_3D_Object *obj);
|
||||
};
|
||||
|
||||
struct _Evas_3D_Object
|
||||
{
|
||||
Evas *evas;
|
||||
|
||||
Evas_3D_Object_Type type;
|
||||
int ref_count;
|
||||
Evas_3D_Object_Func func;
|
||||
|
||||
Eina_Bool dirty[EVAS_3D_STATE_MAX];
|
||||
};
|
||||
|
||||
struct _Evas_3D_Scene
|
||||
{
|
||||
Evas_3D_Object base;
|
||||
|
||||
Evas_3D_Node *root_node;
|
||||
Evas_3D_Node *camera_node;
|
||||
Evas_Color bg_color;
|
||||
|
||||
void *surface;
|
||||
int w, h;
|
||||
Eina_List *images;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Node_Mesh
|
||||
{
|
||||
Evas_3D_Node *node;
|
||||
Evas_3D_Mesh *mesh;
|
||||
int frame;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Node
|
||||
{
|
||||
Evas_3D_Object base;
|
||||
|
||||
Eina_List *members;
|
||||
Evas_3D_Node *parent;
|
||||
|
||||
Evas_Vec3 position;
|
||||
Evas_Vec4 orientation;
|
||||
Evas_Vec3 scale;
|
||||
|
||||
Evas_Vec3 position_world;
|
||||
Evas_Vec4 orientation_world;
|
||||
Evas_Vec3 scale_world;
|
||||
|
||||
Eina_Bool position_inherit;
|
||||
Eina_Bool orientation_inherit;
|
||||
Eina_Bool scale_inherit;
|
||||
|
||||
Evas_Box3 aabb;
|
||||
|
||||
Evas_3D_Node_Type type;
|
||||
|
||||
/* Camera node. */
|
||||
union {
|
||||
struct {
|
||||
Evas_3D_Camera *camera;
|
||||
Evas_Mat4 matrix_world_to_eye;
|
||||
} camera;
|
||||
|
||||
struct {
|
||||
Evas_3D_Light *light;
|
||||
Evas_Mat4 matrix_local_to_world;
|
||||
} light;
|
||||
|
||||
struct {
|
||||
Eina_List *meshes;
|
||||
Eina_Hash *node_meshes;
|
||||
Evas_Mat4 matrix_local_to_world;
|
||||
} mesh;
|
||||
} data;
|
||||
|
||||
/* Scene using this node as root. */
|
||||
Eina_Hash *scenes_root;
|
||||
|
||||
/* Scene using this node as camera. */
|
||||
Eina_Hash *scenes_camera;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Camera
|
||||
{
|
||||
Evas_3D_Object base;
|
||||
|
||||
Evas_Mat4 projection;
|
||||
Eina_Hash *nodes;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Light
|
||||
{
|
||||
Evas_3D_Object base;
|
||||
|
||||
Evas_Color ambient;
|
||||
Evas_Color diffuse;
|
||||
Evas_Color specular;
|
||||
|
||||
Eina_Bool directional;
|
||||
Evas_Real spot_exp;
|
||||
Evas_Real spot_cutoff;
|
||||
Evas_Real spot_cutoff_cos;
|
||||
|
||||
Eina_Bool enable_attenuation;
|
||||
Evas_Real atten_const;
|
||||
Evas_Real atten_linear;
|
||||
Evas_Real atten_quad;
|
||||
|
||||
Eina_Hash *nodes;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Vertex_Buffer
|
||||
{
|
||||
int element_count;
|
||||
int stride;
|
||||
void *data;
|
||||
int size;
|
||||
Eina_Bool owns_data;
|
||||
Eina_Bool mapped;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Interpolate_Vertex_Buffer
|
||||
{
|
||||
void *data0;
|
||||
int stride0;
|
||||
int size0;
|
||||
|
||||
void *data1;
|
||||
int stride1;
|
||||
int size1;
|
||||
|
||||
Evas_Real weight;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Mesh_Frame
|
||||
{
|
||||
Evas_3D_Mesh *mesh;
|
||||
|
||||
int frame;
|
||||
Evas_3D_Material *material;
|
||||
Evas_Box3 aabb;
|
||||
|
||||
Evas_3D_Vertex_Buffer vertices[EVAS_3D_VERTEX_ATTRIB_COUNT];
|
||||
};
|
||||
|
||||
struct _Evas_3D_Mesh
|
||||
{
|
||||
Evas_3D_Object base;
|
||||
|
||||
Evas_3D_Shade_Mode shade_mode;
|
||||
|
||||
int vertex_count;
|
||||
int frame_count;
|
||||
Eina_List *frames;
|
||||
|
||||
Evas_3D_Index_Format index_format;
|
||||
int index_count;
|
||||
void *indices;
|
||||
int index_size;
|
||||
Eina_Bool owns_indices;
|
||||
Eina_Bool index_mapped;
|
||||
|
||||
Evas_3D_Vertex_Assembly assembly;
|
||||
|
||||
Eina_Hash *nodes;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Texture
|
||||
{
|
||||
Evas_3D_Object base;
|
||||
|
||||
/* List of materials using this texture. */
|
||||
Eina_Hash *materials;
|
||||
|
||||
/* Proxy data. */
|
||||
Evas_Object *source;
|
||||
Eina_Bool proxy_rendering;
|
||||
void *proxy_surface;
|
||||
|
||||
/* Engine-side object. */
|
||||
void *engine_data;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Material
|
||||
{
|
||||
Evas_3D_Object base;
|
||||
|
||||
struct {
|
||||
Eina_Bool enable;
|
||||
Evas_Color color;
|
||||
Evas_3D_Texture *texture;
|
||||
} attribs[EVAS_3D_MATERIAL_ATTRIB_COUNT];
|
||||
|
||||
Evas_Real shininess;
|
||||
|
||||
Eina_Hash *meshes;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Scene_Data
|
||||
{
|
||||
Evas_Color bg_color;
|
||||
Evas_3D_Node *camera_node;
|
||||
Eina_List *light_nodes;
|
||||
Eina_List *mesh_nodes;
|
||||
};
|
||||
|
||||
struct _Evas_3D_Pick_Data
|
||||
{
|
||||
/* Input */
|
||||
Evas_Real x, y;
|
||||
Evas_Mat4 matrix_vp;
|
||||
Evas_Ray3 ray_world;
|
||||
|
||||
/* Output */
|
||||
Eina_Bool picked;
|
||||
Evas_Real z;
|
||||
Evas_3D_Node *node;
|
||||
Evas_3D_Mesh *mesh;
|
||||
Evas_Real u, v;
|
||||
Evas_Real s, t;
|
||||
};
|
||||
|
||||
/* Object generic functions. */
|
||||
void evas_3d_object_init(Evas_3D_Object *obj, Evas *e, Evas_3D_Object_Type type, const Evas_3D_Object_Func *func);
|
||||
Evas *evas_3d_object_evas_get(const Evas_3D_Object *obj);
|
||||
Evas_3D_Object_Type evas_3d_object_type_get(const Evas_3D_Object *obj);
|
||||
|
||||
void evas_3d_object_reference(Evas_3D_Object *obj);
|
||||
void evas_3d_object_unreference(Evas_3D_Object *obj);
|
||||
int evas_3d_object_reference_count_get(const Evas_3D_Object *obj);
|
||||
|
||||
void evas_3d_object_change(Evas_3D_Object *obj, Evas_3D_State state, Evas_3D_Object *ref);
|
||||
Eina_Bool evas_3d_object_dirty_get(const Evas_3D_Object *obj, Evas_3D_State state);
|
||||
void evas_3d_object_update(Evas_3D_Object *obj);
|
||||
void evas_3d_object_update_done(Evas_3D_Object *obj);
|
||||
|
||||
/* Node functions. */
|
||||
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_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);
|
||||
void evas_3d_node_scene_camera_add(Evas_3D_Node *node, Evas_3D_Scene *scene);
|
||||
void evas_3d_node_scene_camera_del(Evas_3D_Node *node, Evas_3D_Scene *scene);
|
||||
|
||||
/* Camera functions. */
|
||||
void evas_3d_camera_node_add(Evas_3D_Camera *camera, Evas_3D_Node *node);
|
||||
void evas_3d_camera_node_del(Evas_3D_Camera *camera, Evas_3D_Node *node);
|
||||
|
||||
/* Light functions. */
|
||||
void evas_3d_light_node_add(Evas_3D_Light *light, Evas_3D_Node *node);
|
||||
void evas_3d_light_node_del(Evas_3D_Light *light, Evas_3D_Node *node);
|
||||
|
||||
/* Mesh functions. */
|
||||
void evas_3d_mesh_node_add(Evas_3D_Mesh *mesh, Evas_3D_Node *node);
|
||||
void evas_3d_mesh_node_del(Evas_3D_Mesh *mesh, Evas_3D_Node *node);
|
||||
|
||||
void evas_3d_mesh_interpolate_vertex_buffer_get(Evas_3D_Mesh *mesh, int frame, Evas_3D_Vertex_Attrib attrib, Evas_3D_Vertex_Buffer *buffer0, Evas_3D_Vertex_Buffer *buffer1, Evas_Real *weight);
|
||||
|
||||
void evas_3d_mesh_file_md2_set(Evas_3D_Mesh *mesh, const char *file);
|
||||
|
||||
/* Texture functions. */
|
||||
void evas_3d_texture_material_add(Evas_3D_Texture *texture, Evas_3D_Material *material);
|
||||
void evas_3d_texture_material_del(Evas_3D_Texture *texture, Evas_3D_Material *material);
|
||||
|
||||
/* Material functions. */
|
||||
void evas_3d_material_mesh_add(Evas_3D_Material *material, Evas_3D_Mesh *mesh);
|
||||
void evas_3d_material_mesh_del(Evas_3D_Material *material, Evas_3D_Mesh *mesh);
|
||||
|
||||
/* Scene functions. */
|
||||
void evas_3d_scene_data_init(Evas_3D_Scene_Data *data);
|
||||
void evas_3d_scene_data_fini(Evas_3D_Scene_Data *data);
|
File diff suppressed because it is too large
Load Diff
|
@ -16,6 +16,7 @@
|
|||
#include "../common/language/evas_bidi_utils.h"
|
||||
#include "../common/language/evas_language_utils.h"
|
||||
|
||||
#include "evas_3d_private.h"
|
||||
|
||||
#define RENDER_METHOD_INVALID 0x00000000
|
||||
|
||||
|
@ -46,6 +47,7 @@ typedef struct _Evas_Coord_Touch_Point Evas_Coord_Touch_Point;
|
|||
typedef struct _Evas_Object_Proxy_Data Evas_Object_Proxy_Data;
|
||||
typedef struct _Evas_Object_Map_Data Evas_Object_Map_Data;
|
||||
typedef struct _Evas_Proxy_Render_Data Evas_Proxy_Render_Data;
|
||||
typedef struct _Evas_Object_3D_Data Evas_Object_3D_Data;
|
||||
|
||||
typedef struct _Evas_Object_Protected_State Evas_Object_Protected_State;
|
||||
typedef struct _Evas_Object_Protected_Data Evas_Object_Protected_Data;
|
||||
|
@ -512,6 +514,7 @@ struct _Evas_Map
|
|||
struct _Evas_Object_Proxy_Data
|
||||
{
|
||||
Eina_List *proxies;
|
||||
Eina_List *proxy_textures;
|
||||
void *surface;
|
||||
int w,h;
|
||||
Eina_List *src_event_in;
|
||||
|
@ -537,6 +540,12 @@ struct _Evas_Object_Map_Data
|
|||
RGBA_Map *spans;
|
||||
};
|
||||
|
||||
struct _Evas_Object_3D_Data
|
||||
{
|
||||
void *surface;
|
||||
int w, h;
|
||||
};
|
||||
|
||||
struct _Evas_Object_Protected_State
|
||||
{
|
||||
Evas_Object_Protected_Data *clipper;
|
||||
|
@ -603,6 +612,7 @@ struct _Evas_Object_Protected_Data
|
|||
// Eina_Cow pointer be careful when writing to it
|
||||
const Evas_Object_Proxy_Data *proxy;
|
||||
const Evas_Object_Map_Data *map;
|
||||
const Evas_Object_3D_Data *data_3d;
|
||||
|
||||
// Pointer to the Evas_Object itself
|
||||
Evas_Object *object;
|
||||
|
@ -923,6 +933,26 @@ struct _Evas_Func
|
|||
Eina_Bool (*pixel_alpha_get) (void *image, int x, int y, DATA8 *alpha, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);
|
||||
|
||||
void (*context_flush) (void *data);
|
||||
|
||||
/* 3D features */
|
||||
void *(*drawable_new) (void *data, int w, int h, int alpha);
|
||||
void (*drawable_free) (void *data, void *drawable);
|
||||
void (*drawable_size_get) (void *data, void *drawable, int *w, int *h);
|
||||
void *(*image_drawable_set) (void *data, void *image, void *drawable);
|
||||
|
||||
void (*drawable_scene_render) (void *data, void *drawable, void *scene_data);
|
||||
|
||||
void *(*texture_new) (void *data);
|
||||
void (*texture_free) (void *data, void *texture);
|
||||
void (*texture_data_set) (void *data, void *texture, Evas_3D_Color_Format format, Evas_3D_Pixel_Format pixel_format, int w, int h, const void *pixels);
|
||||
void (*texture_file_set) (void *data, void *texture, const char *file, const char *key);
|
||||
void (*texture_color_format_get) (void *data, void *texture, Evas_3D_Color_Format *format);
|
||||
void (*texture_size_get) (void *data, void *texture, int *w, int *h);
|
||||
void (*texture_wrap_set) (void *data, void *texture, Evas_3D_Wrap_Mode s, Evas_3D_Wrap_Mode t);
|
||||
void (*texture_wrap_get) (void *data, void *texture, Evas_3D_Wrap_Mode *s, Evas_3D_Wrap_Mode *t);
|
||||
void (*texture_filter_set) (void *data, void *texture, Evas_3D_Texture_Filter min, Evas_3D_Texture_Filter mag);
|
||||
void (*texture_filter_get) (void *data, void *texture, Evas_3D_Texture_Filter *min, Evas_3D_Texture_Filter *mag);
|
||||
void (*texture_image_set) (void *data, void *texture, void *image);
|
||||
};
|
||||
|
||||
struct _Evas_Image_Save_Func
|
||||
|
@ -1285,6 +1315,8 @@ extern Eina_Cow *evas_object_proxy_cow;
|
|||
extern Eina_Cow *evas_object_map_cow;
|
||||
extern Eina_Cow *evas_object_state_cow;
|
||||
|
||||
extern Eina_Cow *evas_object_3d_cow;
|
||||
|
||||
extern Eina_Cow *evas_object_image_pixels_cow;
|
||||
extern Eina_Cow *evas_object_image_load_opts_cow;
|
||||
extern Eina_Cow *evas_object_image_state_cow;
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,37 @@
|
|||
#ifndef EVAS_GL_COMMON_H
|
||||
# error You shall not include this header directly
|
||||
#endif
|
||||
|
||||
typedef struct _E3D_Texture E3D_Texture;
|
||||
typedef struct _E3D_Drawable E3D_Drawable;
|
||||
typedef struct _E3D_Renderer E3D_Renderer;
|
||||
|
||||
/* Texture */
|
||||
E3D_Texture *e3d_texture_new(void);
|
||||
void e3d_texture_free(E3D_Texture *texture);
|
||||
|
||||
void e3d_texture_data_set(E3D_Texture *texture, Evas_3D_Color_Format format, Evas_3D_Pixel_Format pixel_format, int w, int h, const void *data);
|
||||
void e3d_texture_file_set(E3D_Texture *texture, const char *file, const char *key);
|
||||
Evas_3D_Color_Format e3d_texture_color_format_get(E3D_Texture *texture);
|
||||
void e3d_texture_size_get(const E3D_Texture *texture, int *w, int *h);
|
||||
|
||||
void e3d_texture_import(E3D_Texture *texture, GLuint tex);
|
||||
Eina_Bool e3d_texture_is_imported_get(const E3D_Texture *texture);
|
||||
|
||||
void e3d_texture_wrap_set(E3D_Texture *texture, Evas_3D_Wrap_Mode s, Evas_3D_Wrap_Mode t);
|
||||
void e3d_texture_wrap_get(const E3D_Texture *texture, Evas_3D_Wrap_Mode *s, Evas_3D_Wrap_Mode *t);
|
||||
|
||||
void e3d_texture_filter_set(E3D_Texture *texture, Evas_3D_Texture_Filter min, Evas_3D_Texture_Filter mag);
|
||||
void e3d_texture_filter_get(const E3D_Texture *texture, Evas_3D_Texture_Filter *min, Evas_3D_Texture_Filter *mag);
|
||||
|
||||
/* Drawable */
|
||||
E3D_Drawable *e3d_drawable_new(int w, int h, int alpha, GLenum depth_format, GLenum stencil_format);
|
||||
void e3d_drawable_free(E3D_Drawable *drawable);
|
||||
void e3d_drawable_scene_render(E3D_Drawable *drawable, E3D_Renderer *renderer, Evas_3D_Scene_Data *data);
|
||||
void e3d_drawable_size_get(E3D_Drawable *drawable, int *w, int *h);
|
||||
GLuint e3d_drawable_texture_id_get(E3D_Drawable *drawable);
|
||||
GLenum e3d_drawable_format_get(E3D_Drawable *drawable);
|
||||
|
||||
/* Renderer */
|
||||
E3D_Renderer *e3d_renderer_new(void);
|
||||
void e3d_renderer_free(E3D_Renderer *renderer);
|
|
@ -0,0 +1,145 @@
|
|||
#ifndef EVAS_GL_3D_PRIVATE_H
|
||||
#define EVAS_GL_3D_PRIVATE_H
|
||||
|
||||
#include "evas_gl_common.h"
|
||||
|
||||
typedef struct _E3D_Program E3D_Program;
|
||||
typedef struct _E3D_Draw_Data E3D_Draw_Data;
|
||||
typedef unsigned long E3D_Shader_Flag;
|
||||
|
||||
#define E3D_SHADER_FLAG_NORMALIZE_NORMALS (1 << 0)
|
||||
#define E3D_SHADER_FLAG_VERTEX_POSITION (1 << 1)
|
||||
#define E3D_SHADER_FLAG_VERTEX_POSITION_BLEND (1 << 2)
|
||||
#define E3D_SHADER_FLAG_VERTEX_NORMAL (1 << 3)
|
||||
#define E3D_SHADER_FLAG_VERTEX_NORMAL_BLEND (1 << 4)
|
||||
#define E3D_SHADER_FLAG_VERTEX_TANGENT (1 << 5)
|
||||
#define E3D_SHADER_FLAG_VERTEX_TANGENT_BLEND (1 << 6)
|
||||
#define E3D_SHADER_FLAG_VERTEX_COLOR (1 << 7)
|
||||
#define E3D_SHADER_FLAG_VERTEX_COLOR_BLEND (1 << 8)
|
||||
#define E3D_SHADER_FLAG_VERTEX_TEXCOORD (1 << 9)
|
||||
#define E3D_SHADER_FLAG_VERTEX_TEXCOORD_BLEND (1 << 10)
|
||||
#define E3D_SHADER_FLAG_LIGHT_DIRECTIONAL (1 << 11)
|
||||
#define E3D_SHADER_FLAG_LIGHT_SPOT (1 << 12)
|
||||
#define E3D_SHADER_FLAG_LIGHT_ATTENUATION (1 << 13)
|
||||
#define E3D_SHADER_FLAG_AMBIENT (1 << 14)
|
||||
#define E3D_SHADER_FLAG_DIFFUSE (1 << 15)
|
||||
#define E3D_SHADER_FLAG_SPECULAR (1 << 16)
|
||||
#define E3D_SHADER_FLAG_EMISSION (1 << 17)
|
||||
#define E3D_SHADER_FLAG_DIFFUSE_TEXTURE (1 << 19)
|
||||
#define E3D_SHADER_FLAG_AMBIENT_TEXTURE (1 << 20)
|
||||
#define E3D_SHADER_FLAG_SPECULAR_TEXTURE (1 << 21)
|
||||
#define E3D_SHADER_FLAG_EMISSION_TEXTURE (1 << 22)
|
||||
#define E3D_SHADER_FLAG_NORMAL_TEXTURE (1 << 23)
|
||||
#define E3D_SHADER_FLAG_DIFFUSE_TEXTURE_BLEND (1 << 24)
|
||||
#define E3D_SHADER_FLAG_AMBIENT_TEXTURE_BLEND (1 << 25)
|
||||
#define E3D_SHADER_FLAG_SPECULAR_TEXTURE_BLEND (1 << 26)
|
||||
#define E3D_SHADER_FLAG_EMISSION_TEXTURE_BLEND (1 << 27)
|
||||
#define E3D_SHADER_FLAG_NORMAL_TEXTURE_BLEND (1 << 28)
|
||||
|
||||
static inline Eina_Bool
|
||||
_flags_need_tex_coord(E3D_Shader_Flag flags)
|
||||
{
|
||||
return (flags & E3D_SHADER_FLAG_AMBIENT_TEXTURE) ||
|
||||
(flags & E3D_SHADER_FLAG_DIFFUSE_TEXTURE) ||
|
||||
(flags & E3D_SHADER_FLAG_SPECULAR_TEXTURE) ||
|
||||
(flags & E3D_SHADER_FLAG_EMISSION_TEXTURE) ||
|
||||
(flags & E3D_SHADER_FLAG_NORMAL_TEXTURE);
|
||||
}
|
||||
|
||||
struct _E3D_Draw_Data
|
||||
{
|
||||
E3D_Shader_Flag flags;
|
||||
Evas_3D_Shade_Mode mode;
|
||||
|
||||
Evas_Mat4 matrix_mvp;
|
||||
Evas_Mat4 matrix_mv;
|
||||
Evas_Mat3 matrix_normal;
|
||||
|
||||
struct {
|
||||
Evas_3D_Vertex_Buffer vertex0;
|
||||
Evas_3D_Vertex_Buffer vertex1;
|
||||
Evas_Real weight;
|
||||
} vertices[EVAS_3D_VERTEX_ATTRIB_COUNT];
|
||||
|
||||
Evas_3D_Vertex_Assembly assembly;
|
||||
int vertex_count;
|
||||
int index_count;
|
||||
Evas_3D_Index_Format index_format;
|
||||
const void *indices;
|
||||
|
||||
GLint texture_count;
|
||||
|
||||
struct {
|
||||
Evas_Color color;
|
||||
GLint sampler0;
|
||||
GLint sampler1;
|
||||
E3D_Texture *tex0;
|
||||
E3D_Texture *tex1;
|
||||
Evas_Real texture_weight;
|
||||
} materials[EVAS_3D_MATERIAL_ATTRIB_COUNT];
|
||||
|
||||
Evas_Real shininess;
|
||||
|
||||
struct {
|
||||
Evas_Vec4 position;
|
||||
Evas_Vec3 spot_dir;
|
||||
Evas_Real spot_exp;
|
||||
Evas_Real spot_cutoff_cos;
|
||||
Evas_Vec3 atten;
|
||||
Evas_Color ambient;
|
||||
Evas_Color diffuse;
|
||||
Evas_Color specular;
|
||||
} light;
|
||||
};
|
||||
|
||||
struct _E3D_Texture
|
||||
{
|
||||
int w, h;
|
||||
|
||||
Eina_Bool is_imported;
|
||||
GLuint tex;
|
||||
GLenum format;
|
||||
|
||||
Eina_Bool wrap_dirty;
|
||||
GLenum wrap_s;
|
||||
GLenum wrap_t;
|
||||
|
||||
Eina_Bool filter_dirty;
|
||||
GLenum filter_min;
|
||||
GLenum filter_mag;
|
||||
};
|
||||
|
||||
struct _E3D_Drawable
|
||||
{
|
||||
int w, h;
|
||||
int alpha;
|
||||
GLenum format;
|
||||
GLenum depth_format;
|
||||
GLenum stencil_format;
|
||||
|
||||
GLuint tex;
|
||||
GLuint fbo;
|
||||
GLuint depth_stencil_buf;
|
||||
GLuint depth_buf;
|
||||
GLuint stencil_buf;
|
||||
};
|
||||
|
||||
/* Texture internal functions. */
|
||||
void e3d_texture_param_update(E3D_Texture *texture);
|
||||
|
||||
/* Program */
|
||||
E3D_Program *e3d_program_new(Evas_3D_Shade_Mode mode, E3D_Shader_Flag flags);
|
||||
void e3d_program_free(E3D_Program *program);
|
||||
GLuint e3d_program_id_get(const E3D_Program *program);
|
||||
Evas_3D_Shade_Mode e3d_program_shade_mode_get(const E3D_Program *program);
|
||||
E3D_Shader_Flag e3d_program_shader_flags_get(const E3D_Program *program);
|
||||
void e3d_program_uniform_upload(E3D_Program *program, const E3D_Draw_Data *data);
|
||||
|
||||
/* Renderer */
|
||||
void e3d_renderer_target_set(E3D_Renderer *renderer, E3D_Drawable *target);
|
||||
void e3d_renderer_viewport_set(E3D_Renderer *renderer, int x, int y, int w, int h);
|
||||
void e3d_renderer_clear(E3D_Renderer *renderer, const Evas_Color *color);
|
||||
void e3d_renderer_draw(E3D_Renderer *renderer, E3D_Draw_Data *data);
|
||||
void e3d_renderer_flush(E3D_Renderer *renderer);
|
||||
|
||||
#endif /* EVAS_GL_3D_PRIVATE_H */
|
|
@ -0,0 +1,284 @@
|
|||
#include "evas_gl_private.h"
|
||||
#include "evas_gl_3d_private.h"
|
||||
|
||||
#define E3D_MAX_TEXTURE_COUNT 8
|
||||
#define E3D_MAX_VERTEX_ATTRIB_COUNT 8
|
||||
|
||||
struct _E3D_Renderer
|
||||
{
|
||||
Eina_List *programs;
|
||||
|
||||
GLuint fbo;
|
||||
GLuint program;
|
||||
E3D_Texture *textures[E3D_MAX_TEXTURE_COUNT];
|
||||
|
||||
Eina_Bool vertex_attrib_enable[E3D_MAX_VERTEX_ATTRIB_COUNT];
|
||||
Eina_Bool depth_test_enable;
|
||||
};
|
||||
|
||||
static inline GLenum
|
||||
_gl_assembly_get(Evas_3D_Vertex_Assembly assembly)
|
||||
{
|
||||
switch (assembly)
|
||||
{
|
||||
case EVAS_3D_VERTEX_ASSEMBLY_POINTS:
|
||||
return GL_POINTS;
|
||||
case EVAS_3D_VERTEX_ASSEMBLY_LINES:
|
||||
return GL_LINES;
|
||||
case EVAS_3D_VERTEX_ASSEMBLY_LINE_STRIP:
|
||||
return GL_LINE_STRIP;
|
||||
case EVAS_3D_VERTEX_ASSEMBLY_LINE_LOOP:
|
||||
return GL_LINE_LOOP;
|
||||
case EVAS_3D_VERTEX_ASSEMBLY_TRIANGLES:
|
||||
return GL_TRIANGLES;
|
||||
case EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_STRIP:
|
||||
return GL_TRIANGLE_STRIP;
|
||||
case EVAS_3D_VERTEX_ASSEMBLY_TRIANGLE_FAN:
|
||||
return GL_TRIANGLE_FAN;
|
||||
default:
|
||||
return GL_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_vertex_attrib_array_enable(E3D_Renderer *renderer, int index)
|
||||
{
|
||||
if (renderer->vertex_attrib_enable[index])
|
||||
return;
|
||||
|
||||
glEnableVertexAttribArray(index);
|
||||
renderer->vertex_attrib_enable[index] = EINA_TRUE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_vertex_attrib_array_disable(E3D_Renderer *renderer, int index)
|
||||
{
|
||||
if (!renderer->vertex_attrib_enable[index])
|
||||
return;
|
||||
|
||||
glDisableVertexAttribArray(index);
|
||||
renderer->vertex_attrib_enable[index] = EINA_FALSE;
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_vertex_attrib_pointer_set(E3D_Renderer *renderer EINA_UNUSED, int index,
|
||||
const Evas_3D_Vertex_Buffer *buffer)
|
||||
{
|
||||
glVertexAttribPointer(index, buffer->element_count, GL_FLOAT,
|
||||
GL_FALSE, buffer->stride, buffer->data);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_elements_draw(E3D_Renderer *renderer EINA_UNUSED, Evas_3D_Vertex_Assembly assembly,
|
||||
int count, Evas_3D_Index_Format format, const void *indices)
|
||||
{
|
||||
GLenum mode = _gl_assembly_get(assembly);
|
||||
|
||||
if (format == EVAS_3D_INDEX_FORMAT_UNSIGNED_BYTE)
|
||||
glDrawElements(mode, count, GL_UNSIGNED_BYTE, indices);
|
||||
else if (format == EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT)
|
||||
glDrawElements(mode, count, GL_UNSIGNED_SHORT, indices);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_array_draw(E3D_Renderer *renderer EINA_UNUSED,
|
||||
Evas_3D_Vertex_Assembly assembly, int count)
|
||||
{
|
||||
GLenum mode = _gl_assembly_get(assembly);
|
||||
|
||||
glDrawArrays(mode, 0, count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_program_use(E3D_Renderer *renderer ,E3D_Program *program)
|
||||
{
|
||||
GLuint prog = e3d_program_id_get(program);
|
||||
|
||||
if (renderer->program != prog)
|
||||
{
|
||||
glUseProgram(prog);
|
||||
renderer->program = prog;
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_texture_bind(E3D_Renderer *renderer, E3D_Draw_Data *data)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < EVAS_3D_MATERIAL_ATTRIB_COUNT; i++)
|
||||
{
|
||||
if (data->materials[i].tex0)
|
||||
{
|
||||
if (renderer->textures[data->materials[i].sampler0] != data->materials[i].tex0)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + data->materials[i].sampler0);
|
||||
glBindTexture(GL_TEXTURE_2D, data->materials[i].tex0->tex);
|
||||
e3d_texture_param_update(data->materials[i].tex0);
|
||||
|
||||
renderer->textures[data->materials[i].sampler0] = data->materials[i].tex0;
|
||||
}
|
||||
}
|
||||
|
||||
if (data->materials[i].tex1)
|
||||
{
|
||||
if (renderer->textures[data->materials[i].sampler1] != data->materials[i].tex1)
|
||||
{
|
||||
glActiveTexture(GL_TEXTURE0 + data->materials[i].sampler1);
|
||||
glBindTexture(GL_TEXTURE_2D, data->materials[i].tex1->tex);
|
||||
e3d_texture_param_update(data->materials[i].tex1);
|
||||
|
||||
renderer->textures[data->materials[i].sampler1] = data->materials[i].tex1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void
|
||||
_renderer_depth_test_enable(E3D_Renderer *renderer, Eina_Bool enable)
|
||||
{
|
||||
if (renderer->depth_test_enable != enable)
|
||||
{
|
||||
if (enable)
|
||||
{
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
/* Use default depth func. */
|
||||
}
|
||||
else
|
||||
{
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
}
|
||||
|
||||
renderer->depth_test_enable = enable;
|
||||
}
|
||||
}
|
||||
|
||||
E3D_Renderer *
|
||||
e3d_renderer_new(void)
|
||||
{
|
||||
E3D_Renderer *renderer = NULL;
|
||||
|
||||
renderer = (E3D_Renderer *)calloc(1, sizeof(E3D_Renderer));
|
||||
|
||||
if (renderer == NULL)
|
||||
{
|
||||
ERR("Failed to allocate memory.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return renderer;
|
||||
}
|
||||
|
||||
void
|
||||
e3d_renderer_free(E3D_Renderer *renderer)
|
||||
{
|
||||
Eina_List *l;
|
||||
E3D_Program *p;
|
||||
|
||||
EINA_LIST_FOREACH(renderer->programs, l, p)
|
||||
{
|
||||
e3d_program_free(p);
|
||||
}
|
||||
|
||||
eina_list_free(renderer->programs);
|
||||
}
|
||||
|
||||
void
|
||||
e3d_renderer_target_set(E3D_Renderer *renderer, E3D_Drawable *target)
|
||||
{
|
||||
if (renderer->fbo == target->fbo)
|
||||
return;
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, target->fbo);
|
||||
glViewport(0, 0, target->w, target->h);
|
||||
renderer->fbo = target->fbo;
|
||||
}
|
||||
|
||||
void
|
||||
e3d_renderer_clear(E3D_Renderer *renderer EINA_UNUSED, const Evas_Color *color)
|
||||
{
|
||||
glClearColor(color->r, color->g, color->b, color->a);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
}
|
||||
|
||||
void
|
||||
e3d_renderer_draw(E3D_Renderer *renderer, E3D_Draw_Data *data)
|
||||
{
|
||||
Eina_List *l;
|
||||
E3D_Program *program = NULL, *p;
|
||||
int i, index = 0;
|
||||
|
||||
_renderer_depth_test_enable(renderer, EINA_TRUE);
|
||||
|
||||
EINA_LIST_FOREACH(renderer->programs, l, p)
|
||||
{
|
||||
if (e3d_program_shade_mode_get(p) == data->mode &&
|
||||
e3d_program_shader_flags_get(p) == data->flags)
|
||||
{
|
||||
program = p;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (program == NULL)
|
||||
{
|
||||
program = e3d_program_new(data->mode, data->flags);
|
||||
|
||||
if (program == NULL)
|
||||
{
|
||||
ERR("Failed to create shader program.");
|
||||
return;
|
||||
}
|
||||
|
||||
renderer->programs = eina_list_append(renderer->programs, program);
|
||||
}
|
||||
|
||||
_renderer_program_use(renderer, program);
|
||||
e3d_program_uniform_upload(program, data);
|
||||
_renderer_texture_bind(renderer, data);
|
||||
|
||||
/* Set up vertex attrib pointers. */
|
||||
index = 0;
|
||||
|
||||
for (i = 0; i < EVAS_3D_VERTEX_ATTRIB_COUNT; i++)
|
||||
{
|
||||
const Evas_3D_Vertex_Buffer *buffer;
|
||||
|
||||
buffer = &data->vertices[i].vertex0;
|
||||
|
||||
if (buffer->data != NULL)
|
||||
{
|
||||
_renderer_vertex_attrib_array_enable(renderer, index);
|
||||
_renderer_vertex_attrib_pointer_set(renderer, index, buffer);
|
||||
index++;
|
||||
}
|
||||
|
||||
buffer = &data->vertices[i].vertex1;
|
||||
|
||||
if (buffer->data != NULL)
|
||||
{
|
||||
_renderer_vertex_attrib_array_enable(renderer, index);
|
||||
_renderer_vertex_attrib_pointer_set(renderer, index, buffer);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
while (index < E3D_MAX_VERTEX_ATTRIB_COUNT)
|
||||
_renderer_vertex_attrib_array_disable(renderer, index++);
|
||||
|
||||
if (data->indices)
|
||||
{
|
||||
_renderer_elements_draw(renderer, data->assembly, data->index_count,
|
||||
data->index_format, data->indices);
|
||||
}
|
||||
else
|
||||
{
|
||||
_renderer_array_draw(renderer, data->assembly, data->vertex_count);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
e3d_renderer_flush(E3D_Renderer *renderer EINA_UNUSED)
|
||||
{
|
||||
glFlush();
|
||||
}
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef EVAS_GL_3D_RENDERER_H
|
||||
#define EVAS_GL_3D_RENDERER_H
|
||||
|
||||
|
||||
|
||||
#endif /* EVAS_GL_3D_RENDERER_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -897,4 +897,6 @@ _tex_sub_2d(Evas_Engine_GL_Context *gc, int x, int y, int w, int h, int fmt, int
|
|||
GLERR(__FUNCTION__, __FILE__, __LINE__, "");
|
||||
}
|
||||
|
||||
#include "evas_gl_3d_common.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,6 +67,9 @@ struct _Render_Engine
|
|||
void *get_pixels_data;
|
||||
Evas_Object *obj;
|
||||
} func;
|
||||
|
||||
Evas_GL_X11_Context *context_3d;
|
||||
E3D_Renderer *renderer_3d;
|
||||
};
|
||||
|
||||
static int initted = 0;
|
||||
|
@ -3701,6 +3704,185 @@ eng_context_flush(void *data)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
eng_context_3d_use(void *data)
|
||||
{
|
||||
Render_Engine *re = (Render_Engine *)data;
|
||||
|
||||
if (re->context_3d == NULL)
|
||||
{
|
||||
re->context_3d = eng_gl_context_new(re->win);
|
||||
|
||||
if (re->context_3d == NULL)
|
||||
{
|
||||
ERR("Failed to create OpenGL context for 3D.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
eng_gl_context_use(re->context_3d);
|
||||
}
|
||||
|
||||
static E3D_Renderer *
|
||||
eng_renderer_3d_get(void *data)
|
||||
{
|
||||
Render_Engine *re = (Render_Engine *)data;
|
||||
|
||||
if (re->renderer_3d == NULL)
|
||||
{
|
||||
re->renderer_3d = e3d_renderer_new();
|
||||
|
||||
if (re->renderer_3d == NULL)
|
||||
{
|
||||
ERR("Failed to create 3D renderer.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
return re->renderer_3d;
|
||||
}
|
||||
|
||||
static void *
|
||||
eng_drawable_new(void *data, int w, int h, int alpha)
|
||||
{
|
||||
eng_context_3d_use(data);
|
||||
#ifdef GL_GLES
|
||||
return e3d_drawable_new(w, h, alpha, GL_DEPTH_STENCIL_OES, GL_NONE);
|
||||
#else
|
||||
return e3d_drawable_new(w, h, alpha, GL_DEPTH24_STENCIL8, GL_NONE);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
eng_drawable_free(void *data, void *drawable)
|
||||
{
|
||||
eng_context_3d_use(data);
|
||||
e3d_drawable_free(drawable);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_drawable_size_get(void *data EINA_UNUSED, void *drawable, int *w, int *h)
|
||||
{
|
||||
e3d_drawable_size_get((E3D_Drawable *)drawable, w, h);
|
||||
}
|
||||
|
||||
static void *
|
||||
eng_image_drawable_set(void *data, void *image, void *drawable)
|
||||
{
|
||||
E3D_Drawable *d = (E3D_Drawable *)drawable;
|
||||
Evas_Native_Surface ns;
|
||||
int w, h;
|
||||
|
||||
ns.type = EVAS_NATIVE_SURFACE_OPENGL;
|
||||
ns.data.opengl.texture_id = e3d_drawable_texture_id_get(d);
|
||||
ns.data.opengl.framebuffer_id = 0;
|
||||
ns.data.opengl.internal_format = e3d_drawable_format_get(d);
|
||||
ns.data.opengl.format = e3d_drawable_format_get(d);
|
||||
ns.data.opengl.x = 0;
|
||||
ns.data.opengl.y = 0;
|
||||
e3d_drawable_size_get(d, &w, &h);
|
||||
ns.data.opengl.w = w;
|
||||
ns.data.opengl.h = h;
|
||||
|
||||
return eng_image_native_set(data, image, &ns);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_drawable_scene_render(void *data, void *drawable, void *scene_data)
|
||||
{
|
||||
Render_Engine *re = (Render_Engine *)data;
|
||||
E3D_Renderer *renderer = NULL;
|
||||
|
||||
eng_window_use(re->win);
|
||||
evas_gl_common_context_flush(re->win->gl_context);
|
||||
|
||||
eng_context_3d_use(data);
|
||||
renderer = eng_renderer_3d_get(data);
|
||||
e3d_drawable_scene_render(drawable, renderer, scene_data);
|
||||
}
|
||||
|
||||
static void *
|
||||
eng_texture_new(void *data EINA_UNUSED)
|
||||
{
|
||||
return e3d_texture_new();
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_free(void *data EINA_UNUSED, void *texture)
|
||||
{
|
||||
e3d_texture_free((E3D_Texture *)texture);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_data_set(void *data, void *texture, Evas_3D_Color_Format color_format,
|
||||
Evas_3D_Pixel_Format pixel_format, int w, int h, const void *pixels)
|
||||
{
|
||||
Render_Engine *re = (Render_Engine *)data;
|
||||
eng_window_use(re->win);
|
||||
evas_gl_common_context_flush(re->win->gl_context);
|
||||
eng_context_3d_use(data);
|
||||
|
||||
e3d_texture_data_set((E3D_Texture *)texture, color_format, pixel_format, w, h, pixels);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_file_set(void *data, void *texture, const char *file, const char *key)
|
||||
{
|
||||
Render_Engine *re = (Render_Engine *)data;
|
||||
eng_window_use(re->win);
|
||||
evas_gl_common_context_flush(re->win->gl_context);
|
||||
eng_context_3d_use(data);
|
||||
|
||||
e3d_texture_file_set((E3D_Texture *)texture, file, key);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_color_format_get(void *data EINA_UNUSED, void *texture, Evas_3D_Color_Format *format)
|
||||
{
|
||||
*format = e3d_texture_color_format_get((E3D_Texture *)texture);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_size_get(void *data EINA_UNUSED, void *texture, int *w, int *h)
|
||||
{
|
||||
e3d_texture_size_get((E3D_Texture *)texture, w, h);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_wrap_set(void *data EINA_UNUSED, void *texture,
|
||||
Evas_3D_Wrap_Mode s, Evas_3D_Wrap_Mode t)
|
||||
{
|
||||
e3d_texture_wrap_set((E3D_Texture *)texture, s, t);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_wrap_get(void *data EINA_UNUSED, void *texture,
|
||||
Evas_3D_Wrap_Mode *s, Evas_3D_Wrap_Mode *t)
|
||||
{
|
||||
e3d_texture_wrap_get((E3D_Texture *)texture, s, t);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_filter_set(void *data EINA_UNUSED, void *texture,
|
||||
Evas_3D_Texture_Filter min, Evas_3D_Texture_Filter mag)
|
||||
{
|
||||
e3d_texture_filter_set((E3D_Texture *)texture, min, mag);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_filter_get(void *data EINA_UNUSED, void *texture,
|
||||
Evas_3D_Texture_Filter *min, Evas_3D_Texture_Filter *mag)
|
||||
{
|
||||
e3d_texture_filter_get((E3D_Texture *)texture, min, mag);
|
||||
}
|
||||
|
||||
static void
|
||||
eng_texture_image_set(void *data EINA_UNUSED, void *texture, void *image)
|
||||
{
|
||||
Evas_GL_Image *im = (Evas_GL_Image *)image;
|
||||
e3d_texture_import((E3D_Texture *)texture, im->tex->pt->texture);
|
||||
}
|
||||
|
||||
static int
|
||||
module_open(Evas_Module *em)
|
||||
{
|
||||
|
@ -3825,6 +4007,26 @@ module_open(Evas_Module *em)
|
|||
|
||||
ORD(context_flush);
|
||||
|
||||
/* 3D features */
|
||||
ORD(drawable_new);
|
||||
ORD(drawable_free);
|
||||
ORD(drawable_size_get);
|
||||
ORD(image_drawable_set);
|
||||
|
||||
ORD(drawable_scene_render);
|
||||
|
||||
ORD(texture_new);
|
||||
ORD(texture_free);
|
||||
ORD(texture_data_set);
|
||||
ORD(texture_file_set);
|
||||
ORD(texture_color_format_get);
|
||||
ORD(texture_size_get);
|
||||
ORD(texture_wrap_set);
|
||||
ORD(texture_wrap_get);
|
||||
ORD(texture_filter_set);
|
||||
ORD(texture_filter_get);
|
||||
ORD(texture_image_set);
|
||||
|
||||
/* now advertise out own api */
|
||||
em->functions = (void *)(&func);
|
||||
return 1;
|
||||
|
|
|
@ -58,6 +58,7 @@ extern int _evas_engine_GL_X11_log_dom ;
|
|||
#define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_GL_X11_log_dom, __VA_ARGS__)
|
||||
|
||||
typedef struct _Evas_GL_X11_Window Evas_GL_X11_Window;
|
||||
typedef struct _Evas_GL_X11_Context Evas_GL_X11_Context;
|
||||
|
||||
struct _Evas_GL_X11_Window
|
||||
{
|
||||
|
@ -91,6 +92,20 @@ struct _Evas_GL_X11_Window
|
|||
int surf : 1;
|
||||
};
|
||||
|
||||
struct _Evas_GL_X11_Context
|
||||
{
|
||||
#ifdef GL_GLES
|
||||
EGLDisplay display;
|
||||
EGLContext context;
|
||||
EGLSurface surface;
|
||||
#else
|
||||
Display *display;
|
||||
GLXContext context;
|
||||
GLXWindow glxwin;
|
||||
Window win;
|
||||
#endif
|
||||
};
|
||||
|
||||
Evas_GL_X11_Window *eng_window_new(Display *disp, Window win, int screen,
|
||||
Visual *vis, Colormap cmap,
|
||||
int depth, int w, int h, int indirect,
|
||||
|
@ -104,4 +119,8 @@ void *eng_best_visual_get(Evas_Engine_Info_GL_X11 *einfo);
|
|||
Colormap eng_best_colormap_get(Evas_Engine_Info_GL_X11 *einfo);
|
||||
int eng_best_depth_get(Evas_Engine_Info_GL_X11 *einfo);
|
||||
|
||||
Evas_GL_X11_Context *eng_gl_context_new(Evas_GL_X11_Window *win);
|
||||
void eng_gl_context_free(Evas_GL_X11_Context *context);
|
||||
void eng_gl_context_use(Evas_GL_X11_Context *context);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -849,3 +849,93 @@ eng_best_depth_get(Evas_Engine_Info_GL_X11 *einfo)
|
|||
}
|
||||
return _evas_gl_x11_vi->depth;
|
||||
}
|
||||
|
||||
Evas_GL_X11_Context *
|
||||
eng_gl_context_new(Evas_GL_X11_Window *win)
|
||||
{
|
||||
Evas_GL_X11_Context *ctx;
|
||||
#if GL_GLES
|
||||
int context_attrs[3] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };
|
||||
#endif
|
||||
|
||||
if (!win) return NULL;
|
||||
|
||||
ctx = calloc(1, sizeof(Evas_GL_X11_Context));
|
||||
if (!ctx) return NULL;
|
||||
|
||||
#if GL_GLES
|
||||
ctx->context = eglCreateContext(win->egl_disp, win->egl_config,
|
||||
win->egl_context[0], context_attrs);
|
||||
|
||||
if (!ctx->context)
|
||||
{
|
||||
ERR("EGL context creation failed.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctx->display = win->egl_disp;
|
||||
ctx->surface = win->egl_surface[0];
|
||||
#else
|
||||
ctx->context = glXCreateContext(win->disp, win->visualinfo, win->context, 1);
|
||||
|
||||
if (!ctx->context)
|
||||
{
|
||||
ERR("GLX context creation failed.");
|
||||
goto error;
|
||||
}
|
||||
|
||||
ctx->display = win->disp;
|
||||
ctx->glxwin = win->glxwin;
|
||||
ctx->win = win->win;
|
||||
#endif
|
||||
|
||||
return ctx;
|
||||
|
||||
error:
|
||||
free(ctx);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void
|
||||
eng_gl_context_free(Evas_GL_X11_Context *ctx)
|
||||
{
|
||||
#if GL_GLES
|
||||
eglDestroyContext(ctx->display, ctx->context);
|
||||
#else
|
||||
glXDestroyContext(ctx->display, ctx->context);
|
||||
#endif
|
||||
|
||||
free(ctx);
|
||||
}
|
||||
|
||||
void
|
||||
eng_gl_context_use(Evas_GL_X11_Context *ctx)
|
||||
{
|
||||
#if GL_GLES
|
||||
if (eglMakeCurrent(ctx->display, ctx->surface,
|
||||
ctx->surface, ctx->context) == EGL_FALSE)
|
||||
{
|
||||
ERR("eglMakeCurrent() failed.");
|
||||
}
|
||||
#else
|
||||
if (ctx->glxwin)
|
||||
{
|
||||
if (!glXMakeContextCurrent(ctx->display, ctx->glxwin,
|
||||
ctx->glxwin, ctx->context))
|
||||
{
|
||||
ERR("glXMakeContextCurrent(%p, %p, %p, %p) faild.",
|
||||
(void *)ctx->display, (void *)ctx->glxwin,
|
||||
(void *)ctx->glxwin, (void *)ctx->context);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!glXMakeCurrent(ctx->display, ctx->win, ctx->context))
|
||||
{
|
||||
ERR("glXMakeCurrent(%p, %p, %p) failed.",
|
||||
(void *)ctx->display, (void *)ctx->win,
|
||||
(void *)ctx->context);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2712,6 +2712,22 @@ static Evas_Func func =
|
|||
eng_multi_font_draw,
|
||||
eng_pixel_alpha_get,
|
||||
NULL, // eng_context_flush - software doesn't use it
|
||||
NULL, // eng_drawable_new
|
||||
NULL, // eng_drawable_free
|
||||
NULL, // eng_drawable_size_get
|
||||
NULL, // eng_image_drawable_set
|
||||
NULL, // eng_drawable_render_scene
|
||||
NULL, // eng_texture_new
|
||||
NULL, // eng_texture_free
|
||||
NULL, // eng_texture_data_set
|
||||
NULL, // eng_texture_file_set
|
||||
NULL, // eng_texture_color_format_get
|
||||
NULL, // eng_texture_size_get
|
||||
NULL, // eng_texture_wrap_set
|
||||
NULL, // eng_texture_wrap_get
|
||||
NULL, // eng_texture_filter_set
|
||||
NULL, // eng_texture_filter_get
|
||||
NULL, // eng_texture_image_set
|
||||
/* FUTURE software generic calls go here */
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue