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:
Taekyun Kim 2013-12-27 16:56:30 +09:00 committed by ChunEon Park
parent 96f9353f4c
commit 8fda631730
30 changed files with 10394 additions and 5 deletions

View File

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

View File

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

View File

@ -292,7 +292,6 @@ extern "C" {
#ifdef EFL_EO_API_SUPPORT
#include <Evas_Eo.h>
#endif
#ifdef __cplusplus
}
#endif

289
src/lib/evas/Evas_3D.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 */
};