cedric pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=6dac83e643934573a734491d97b549a6b235c0f5
commit 6dac83e643934573a734491d97b549a6b235c0f5 Author: Bogdan Devichev <b.devic...@samsung.com> Date: Tue May 26 18:49:15 2015 +0200 evas: add API for creation Evas_3D node primitives. Summary: Now mechanism of creation of primitives is similar to model loading. Reviewers: Oleksander, Hermet, raster, cedric Reviewed By: cedric Subscribers: cedric Differential Revision: https://phab.enlightenment.org/D2516 Signed-off-by: Cedric BAIL <ced...@osg.samsung.com> --- src/Makefile_Evas.am | 14 ++ src/lib/evas/Evas_Eo.h | 61 +++++- src/lib/evas/canvas/evas_3d_mesh.c | 13 ++ src/lib/evas/canvas/evas_3d_mesh.eo | 11 +- src/lib/evas/canvas/evas_3d_primitive.c | 162 ++++++++++++++++ src/lib/evas/canvas/evas_3d_primitive.eo | 179 ++++++++++++++++++ .../evas/common3d/primitives/primitive_common.c | 209 +++++++++++++++++++++ .../evas/common3d/primitives/primitive_common.h | 58 ++++++ .../primitives/solids_of_revolution/cone.c | 140 ++++++++++++++ .../primitives/solids_of_revolution/cylinder.c | 136 ++++++++++++++ .../primitives/solids_of_revolution/sphere.c | 189 +++++++++++++++++++ .../primitives/solids_of_revolution/torus.c | 67 +++++++ .../evas/common3d/primitives/surfaces/surface.c | 91 +++++++++ .../evas/common3d/primitives/surfaces/terrain.c | 86 +++++++++ .../primitives/tabulated_primitives/cube.c | 57 ++++++ .../primitives/tabulated_primitives/square.c | 18 ++ src/lib/evas/include/evas_private.h | 23 +++ 17 files changed, 1511 insertions(+), 3 deletions(-) diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index 72f8365..3a2f4af 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -29,6 +29,7 @@ evas_eolian_files = \ lib/evas/canvas/evas_3d_material.eo\ lib/evas/canvas/evas_3d_light.eo\ lib/evas/canvas/evas_3d_mesh.eo\ + lib/evas/canvas/evas_3d_primitive.eo\ lib/evas/canvas/evas_3d_node.eo\ lib/evas/canvas/evas_3d_scene.eo\ lib/evas/canvas/evas_3d_object.eo \ @@ -202,6 +203,7 @@ 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_primitive.c \ lib/evas/canvas/evas_3d_node_callback.h # Model savers/loaders (will be replaced to modules in next commits) @@ -215,6 +217,18 @@ modules/evas/model_savers/obj/evas_model_save_obj.c \ modules/evas/model_savers/ply/evas_model_save_ply.c \ lib/evas/canvas/evas_3d_eet.c +# 3d primitives +lib_evas_libevas_la_SOURCES += \ +lib/evas/common3d/primitives/tabulated_primitives/square.c \ +lib/evas/common3d/primitives/tabulated_primitives/cube.c \ +lib/evas/common3d/primitives/solids_of_revolution/sphere.c \ +lib/evas/common3d/primitives/solids_of_revolution/torus.c \ +lib/evas/common3d/primitives/solids_of_revolution/cylinder.c \ +lib/evas/common3d/primitives/solids_of_revolution/cone.c \ +lib/evas/common3d/primitives/surfaces/surface.c \ +lib/evas/common3d/primitives/surfaces/terrain.c \ +lib/evas/common3d/primitives/primitive_common.c + # Evas_VG lib_evas_libevas_la_SOURCES += \ lib/evas/canvas/evas_object_vg.c \ diff --git a/src/lib/evas/Evas_Eo.h b/src/lib/evas/Evas_Eo.h index c81ce46..e401a51 100644 --- a/src/lib/evas/Evas_Eo.h +++ b/src/lib/evas/Evas_Eo.h @@ -304,6 +304,15 @@ EAPI extern const Eo_Event_Description _EVAS_CANVAS_EVENT_VIEWPORT_RESIZE; */ /** + * @defgroup Evas_3D_Primitive Primitive Object + * @ingroup Evas_3D + * + * A primitive object is an object with necessary data for creating meshes with ptimitive shapes. + * Data from a primitive can be set to Evas_3D_Mesh by using evas_3d_mesh_from_primitive_set() + * function. + */ + +/** * @defgroup Evas_3D_Texture Texture Object * @ingroup Evas_3D * @@ -435,6 +444,33 @@ typedef Eo Evas_3D_Material; #define _EVAS_3D_MATERIAL_EO_CLASS_TYPE /** + * @typedef Evas_3D_Primitive + * + * Primitive object handle + * + * @since 1.15 + * @ingroup Evas_3D_Primitive + */ +typedef Eo Evas_3D_Primitive; + +#define _EVAS_3D_PRIMITIVE_EO_CLASS_TYPE + +/** + * @typedef Evas_3D_Surface_Func + * + * User-defined parametric surface function. + * Used for easy creation of custom surfaces as a primitive. + * + * @since 1.15 + * @ingroup Evas_3D_Primitive + */ +typedef void (Evas_3D_Surface_Func)(Evas_Real *out_x, + Evas_Real *out_y, + Evas_Real *out_z, + Evas_Real a, + Evas_Real b); + +/** * Type of 3D Object * * @since 1.10 @@ -451,6 +487,7 @@ typedef enum _Evas_3D_Object_Type EVAS_3D_OBJECT_TYPE_MESH, EVAS_3D_OBJECT_TYPE_TEXTURE, EVAS_3D_OBJECT_TYPE_MATERIAL, + EVAS_3D_OBJECT_TYPE_PRIMITIVE, } Evas_3D_Object_Type; /** @@ -716,7 +753,7 @@ typedef enum _Evas_3D_Wrap_Mode } Evas_3D_Wrap_Mode; /** - * Mesh Primitive + * Mesh primitive * * @since 1.12 * @ingroup Evas_3D_Types @@ -740,10 +777,28 @@ typedef enum _Evas_3D_Mesh_Primitive /**< Custom surface (can use pointer to users function, precision and texture scale) */ EVAS_3D_MESH_PRIMITIVE_SURFACE, /**< Terrain as surface with pointer to Perlin's noise function */ - EVAS_3D_MESH_PRIMITIVE_TERRAIN + EVAS_3D_MESH_PRIMITIVE_TERRAIN, + /**< Count of supported primitives */ + EVAS_3D_MESH_PRIMITIVE_COUNT } Evas_3D_Mesh_Primitive; /** + * Mode of mesh primitive + * + * @since 1.15 + * @ingroup Evas_3D_Types + */ +typedef enum _Evas_3D_Primitive_Mode +{ + /**< Default mode of primitive */ + EVAS_3D_PRIMITIVE_MODE_DEFAULT = 0, + /**< Primitive without base (supported for cylinder and cone) */ + EVAS_3D_PRIMITIVE_MODE_WITHOUT_BASE, + /**< Ptimitive with alternative UV (supported for sphere)*/ + EVAS_3D_PRIMITIVE_MODE_ALTERNATIVE_UV +} Evas_3D_Primitive_Mode; + +/** * Texture filters * * @since 1.10 @@ -818,6 +873,8 @@ typedef enum _Evas_3D_Material_Attrib #include "canvas/evas_3d_mesh.eo.h" +#include "canvas/evas_3d_primitive.eo.h" + #include "canvas/evas_3d_node.eo.h" #include "canvas/evas_3d_scene.eo.h" diff --git a/src/lib/evas/canvas/evas_3d_mesh.c b/src/lib/evas/canvas/evas_3d_mesh.c index 1b8cc14..f15b42f 100644 --- a/src/lib/evas/canvas/evas_3d_mesh.c +++ b/src/lib/evas/canvas/evas_3d_mesh.c @@ -893,6 +893,19 @@ _evas_3d_mesh_efl_file_save(Eo *obj, Evas_3D_Mesh_Data *pd, return EINA_TRUE; } +EOLIAN static void +_evas_3d_mesh_from_primitive_set(Eo *obj, + Evas_3D_Mesh_Data *pd EINA_UNUSED, + int frame, + Eo *primitive) +{ + if ((primitive == NULL) || (obj == NULL)) return; + + Evas_3D_Primitive_Data *ppd = eo_data_scope_get(primitive, EVAS_3D_PRIMITIVE_CLASS); + + evas_common_set_model_from_primitive(obj, frame, ppd); +} + static inline void _mesh_frame_find(Evas_3D_Mesh_Data *mesh, int frame, Eina_List **l, Eina_List **r) diff --git a/src/lib/evas/canvas/evas_3d_mesh.eo b/src/lib/evas/canvas/evas_3d_mesh.eo index 5789cc0..db0f895 100644 --- a/src/lib/evas/canvas/evas_3d_mesh.eo +++ b/src/lib/evas/canvas/evas_3d_mesh.eo @@ -291,7 +291,16 @@ class Evas_3D_Mesh (Evas_3D_Object, Evas.Common_Interface, Efl.File) @out dfactor: Evas_3D_Blend_Func; /*@ Pointer to receive destination blendin factors key.*/ } } - + from_primitive_set { + /*@ + Set the data of given mesh frame from the given primitive + @ingroup Evas_3D_Mesh + */ + params { + @in frame: int; /*@ Specifies data of which frame of given mesh will be set.*/ + @in primitive: Evas_3D_Primitive *; /*@ Specifies which data will be set.*/ + } + } @property shade_mode { set { /*@ diff --git a/src/lib/evas/canvas/evas_3d_primitive.c b/src/lib/evas/canvas/evas_3d_primitive.c new file mode 100644 index 0000000..34ecab6 --- /dev/null +++ b/src/lib/evas/canvas/evas_3d_primitive.c @@ -0,0 +1,162 @@ +#include "evas_common_private.h" +#include "evas_private.h" + +#define MY_CLASS EVAS_3D_PRIMITIVE_CLASS + +static inline void +_primitive_init(Evas_3D_Primitive_Data *pd) +{ + pd->form = EVAS_3D_MESH_PRIMITIVE_NONE; + pd->ratio = 3.0; + pd->precision = 10; + pd->surface = NULL; + pd->tex_scale.x = 1.0; + pd->tex_scale.y = 1.0; +} + +static inline void +_primitive_fini(Evas_3D_Primitive_Data *pd) +{ + if (pd->surface) + free(pd->surface); +} + +EAPI Evas_3D_Primitive * +evas_3d_primitive_add(Evas *e) +{ + MAGIC_CHECK(e, Evas, MAGIC_EVAS); + return NULL; + MAGIC_CHECK_END(); + Evas_Object *eo_obj = eo_add(MY_CLASS, e); + return eo_obj; +} + +EOLIAN static Eo * +_evas_3d_primitive_eo_base_constructor(Eo *obj, Evas_3D_Primitive_Data *pd) +{ + obj = eo_do_super_ret(obj, MY_CLASS, obj, eo_constructor()); + eo_do(obj, evas_3d_object_type_set(EVAS_3D_OBJECT_TYPE_PRIMITIVE)); + _primitive_init(pd); + + return obj; +} + +EOLIAN static void +_evas_3d_primitive_eo_base_destructor(Eo *obj, Evas_3D_Primitive_Data *pd) +{ + _primitive_fini(pd); + eo_do_super(obj, MY_CLASS, eo_destructor()); +} + +EOLIAN static void +_evas_3d_primitive_form_set(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd, + Evas_3D_Mesh_Primitive form) +{ + if ((form < EVAS_3D_MESH_PRIMITIVE_NONE) || + (form >= EVAS_3D_MESH_PRIMITIVE_COUNT)) + { + ERR("Wrong form of primitive."); + return; + } + + if (pd->form != form) + pd->form = form; +} + +EOLIAN static Evas_3D_Mesh_Primitive +_evas_3d_primitive_form_get(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd) +{ + return pd->form; +} + +EOLIAN static void +_evas_3d_primitive_mode_set(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd, + Evas_3D_Primitive_Mode mode) +{ + if (pd->mode != mode) + pd->mode = mode; +} + +EOLIAN static Evas_3D_Primitive_Mode +_evas_3d_primitive_mode_get(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd) +{ + return pd->mode; +} + +EOLIAN static void +_evas_3d_primitive_ratio_set(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd, + Evas_Real ratio) +{ + pd->ratio = ratio; +} + +EOLIAN static Evas_Real +_evas_3d_primitive_ratio_get(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd) +{ + return pd->ratio; +} + +EOLIAN static void +_evas_3d_primitive_precision_set(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd, + int precision) +{ + if ((precision < 3)) + { + ERR("Precision of Evas_3D_Primitive cannot be less than 3."); + return; + } + + if ((precision >= 100)) + { + ERR("%s\n%s", + "Be careful with precision of Evas_3D_Primitive more than 100.", + "It can give unacceptable result."); + } + + if (pd->precision != precision) + pd->precision = precision; +} + +EOLIAN static int +_evas_3d_primitive_precision_get(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd) +{ + return pd->precision; +} + +EOLIAN static void +_evas_3d_primitive_surface_set(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd, + Evas_3D_Surface_Func surface_func) +{ + pd->surface = surface_func; +} + +EOLIAN static void +_evas_3d_primitive_tex_scale_set(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd, + Evas_Real x, + Evas_Real y) +{ + if (x) pd->tex_scale.x = x; + if (y) pd->tex_scale.y = y; +} + +EOLIAN static void +_evas_3d_primitive_tex_scale_get(Eo *obj EINA_UNUSED, + Evas_3D_Primitive_Data *pd, + Evas_Real *x, + Evas_Real *y) +{ + if (x) *x = pd->tex_scale.x; + if (y) *y = pd->tex_scale.y; +} + +#include "canvas/evas_3d_primitive.eo.c" diff --git a/src/lib/evas/canvas/evas_3d_primitive.eo b/src/lib/evas/canvas/evas_3d_primitive.eo new file mode 100644 index 0000000..e1336c6 --- /dev/null +++ b/src/lib/evas/canvas/evas_3d_primitive.eo @@ -0,0 +1,179 @@ +class Evas_3D_Primitive (Evas_3D_Object, Evas.Common_Interface) +{ + legacy_prefix: null; + data: Evas_3D_Primitive_Data; + + methods { + @property form { + set { + /* + *Set the form of the given primitive. + * + *Form defines which function will be chosen to set data to mesh + *on call of evas_3d_mesh_primitive_set. + * + *Now avaliable next forms of primitives: + *-tabulated primitives: SQUARE and CUBE; + *-solids of revolution: CYLINDER, CONE, SPHERE and TORUS; + *-surfaces: SURFACE and TERRAIN. + * + *Default form is EVAS_3D_MESH_PRIMITIVE_NONE + * + *@ingroup Evas_3D_Primitive + */ + } + get { + /* + *Get the form of the given primitive. + *@see evas_3d_primitive_form_set() + *@return The form of primitive. + *@ingroup Evas_3D_Primitive + */ + } + values { + form: Evas_3D_Mesh_Primitive; /*@ Form of primitive.*/ + } + } + @property mode { + set { + /* + *Set the mode of the given primitive. + * + *Mode defines which function will be chosen to set data to mesh + *on call of evas_3d_mesh_primitive_set. It helps to choose + *alternative algorithm for primitive with given form + *(like cone without base or sphere textured in alternative way). + * + *Now avaliable next mods of primitives: + *-witout base (bases): supported for cylinder and cone; + *-with alternative UV: supported by sphere; + * + *Default form is EVAS_3D_PRIMITIVE_MODE_DEFAULT + * + *@ingroup Evas_3D_Primitive + */ + } + get { + /* + *Get the mode of the given primitive. + *@see evas_3d_primitive_mode_set() + *@return The mode of primitive. + *@ingroup Evas_3D_Primitive + */ + } + values { + mode: Evas_3D_Primitive_Mode; /*@ Mode of primitive.*/ + } + } + @property ratio { + set { + /* + *Set the ratio of the given primitive. + * + *Now ratio uses only in torus as the ratio of the + *major radius and minor radius. For this usage + *Avaliable values is from 1.0 to infinity. + *If ratio for torus has a bad value, + *will be used 3.0 as ratio. Like ratio of usual doughnut. + * + *Default ratio is 3.0 + * + *@ingroup Evas_3D_Primitive + */ + } + get { + /* + *Get the ratio of the given primitive. + *@see evas_3d_primitive_ratio_set() + *@return The ratio of primitive. + *@ingroup Evas_3D_Primitive + */ + } + values { + ratio: Evas_Real; /*@ Ratio of primitive.*/ + } + } + @property precision { + set { + /* + *Set the precision of the given primitive. + * + *Precision uses in all non tabulated primitives and defines + *precision of created primitives. + *Avaliable values is from 3 to infinity. + *But if value will be more than 100, should be a warning + *about possibility of incorrect or slow work. + * + *Default ratio is 10 + * + *@ingroup Evas_3D_Primitive + */ + } + get { + /* + *Get the precision of the given primitive. + *@see evas_3d_primitive_precision_set() + *@return The precision of primitive. + *@ingroup Evas_3D_Primitive + */ + } + values { + precision: int; /*@ Precision of primitive.*/ + } + } + @property surface { + set { + /* + *Set the surface of the given primitive. + * + *Surface uses only in surface primitive and defines + *equation of filling mesh data on call of + *evas_3d_mesh_primitive_set. + * + *It gives possibility to create customers primitives like + *shell, heart, hyperbolic paraboloid etc. See _shell_func in + *examples/evas/evas-3d-visual-test.c or _perlin_terrain in + *modules/evas/primitives/surfaces/terrain.c as an example of usage. + * + *Default surface is NULL + * + *@ingroup Evas_3D_Primitive + */ + } + values { + surface: Evas_3D_Surface_Func *; /*@ Pointer to customers surface function.*/ + } + } + @property tex_scale { + set { + /* + *Set the texture scale of the given primitive. + * + *Texture scale uses in all non tabulated primitives + *and defines scale of texture coords or primitives. + * + *It uses to create periodical textured meshes. + * + *Default tex_scale is {1.0, 1.0} + * + *@ingroup Evas_3D_Primitive + */ + } + get { + /* + *Get the texture scale of the given primitive. + *@see evas_3d_primitive_tex_scale_set() + *@ingroup Evas_3D_Primitive + */ + } + values { + tex_scale_x: Evas_Real; + tex_scale_y: Evas_Real; + } + } + } + implements { + Eo.Base.constructor; + Eo.Base.destructor; + } +} diff --git a/src/lib/evas/common3d/primitives/primitive_common.c b/src/lib/evas/common3d/primitives/primitive_common.c new file mode 100644 index 0000000..066ef3b --- /dev/null +++ b/src/lib/evas/common3d/primitives/primitive_common.c @@ -0,0 +1,209 @@ +#include "primitive_common.h" + +void _set_vertex_data_from_array(Evas_3D_Mesh *mesh, + int frame, + const float *data, + Evas_3D_Vertex_Attrib attr, + int start, + int attr_count, + int line, + int vcount) +{ + float *address, *out; + int stride, i, j; + eo_do(mesh, + evas_3d_mesh_frame_vertex_data_copy_set(frame, attr, 0, NULL), + address = (float *)evas_3d_mesh_frame_vertex_data_map(frame, attr), + stride = evas_3d_mesh_frame_vertex_stride_get(frame, attr)); + if (stride == 0) stride = sizeof(float) * attr_count; + for (i = 0; i < vcount; i++) + { + out = (float *)((char *)address + stride * i); + for (j = 0; j < attr_count; j++) + out[j] = data[start + (line * i) + j]; + } + eo_do(mesh, + evas_3d_mesh_frame_vertex_data_unmap(frame, attr)); +} + +void +_set_vec3_vertex_data(Evas_3D_Mesh *mesh, + int frame, + int vcount, + Evas_Vec3 *data, + Evas_3D_Vertex_Attrib attr) +{ + float *address, *out; + int stride, i; + eo_do(mesh, + evas_3d_mesh_frame_vertex_data_copy_set(frame, attr, 0, NULL), + address = (float *)evas_3d_mesh_frame_vertex_data_map(frame, attr), + stride = evas_3d_mesh_frame_vertex_stride_get(frame, attr)); + if (stride == 0) stride = sizeof(float) * 3; + for (i = 0; i < vcount; i++) + { + out = (float *)((char *)address + stride * i); + out[0] = data[i].x; + out[1] = data[i].y; + out[2] = data[i].z; + } + free(data); + eo_do(mesh, + evas_3d_mesh_frame_vertex_data_unmap(frame, attr)); +} + +void +_set_vec2_vertex_data(Evas_3D_Mesh *mesh, + int frame, + int vcount, + Evas_Vec2 *data, + Evas_3D_Vertex_Attrib attr) +{ + float *address, *out; + int stride, i; + eo_do(mesh, + evas_3d_mesh_frame_vertex_data_copy_set(frame, attr, 0, NULL), + address = (float *)evas_3d_mesh_frame_vertex_data_map(frame, attr), + stride = evas_3d_mesh_frame_vertex_stride_get(frame, attr)); + if (stride == 0) stride = sizeof(float) * 2; + for (i = 0; i < vcount; i++) + { + out = (float *)((char *)address + stride * i); + out[0] = data[i].x; + out[1] = data[i].y; + } + free(data); + eo_do(mesh, + evas_3d_mesh_frame_vertex_data_unmap(frame, attr)); +} + +void +_generate_indices(unsigned short *indices, int a, int b) +{ + int i, j, a1 = a + 1; + unsigned short *index = &indices[0]; + + for (i = 0; i < b; i++) + { + for (j = 0; j < a; j++) + { + *index++ = j + a1 * i; + *index++ = j + a1 * (i + 1); + *index++ = j + 1 + a1 * (i + 1); + + *index++ = j + a1 * i; + *index++ = j + 1 + a1 * i; + *index++ = j + a1 * (i + 1) + 1; + } + } +} + +void +_primitives_vec3_copy(Evas_Vec3 *dst, const Evas_Vec3 *src) +{ + dst->x = src->x; + dst->y = src->y; + dst->z = src->z; +} + +void +_primitives_vec3_subtract(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b) +{ + out->x = a->x - b->x; + out->y = a->y - b->y; + out->z = a->z - b->z; +} + +void +_primitives_vec3_cross_product(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b) +{ + Evas_Vec3 tmp; + + tmp.x = a->y * b->z - a->z * b->y; + tmp.y = a->z * b->x - a->x * b->z; + tmp.z = a->x * b->y - a->y * b->x; + + _primitives_vec3_copy(out, &tmp); +} + +void +_primitives_vec3_normalize(Evas_Vec3 *out) +{ + Evas_Real size = out->x * out->x + out->y *out->y + out->z * out->z; + size = sqrt(size); + out->x /= size; + out->y /= size; + out->z /= size; +} + +void +evas_common_set_model_from_primitive(Evas_3D_Mesh *model, + int frame, + Evas_3D_Primitive_Data *primitive) +{ + Evas_Real ratio = primitive->ratio; + int precision = primitive->precision; + Evas_3D_Surface_Func *surface = primitive->surface; + Evas_Vec2 tex_scale = primitive->tex_scale; + Evas_3D_Primitive_Mode mode = primitive->mode; + + switch (primitive->form) + { + case EVAS_3D_MESH_PRIMITIVE_NONE: + case EVAS_3D_MESH_PRIMITIVE_COUNT: + { + ERR("Primitive with this type cannot be set to mesh."); + break; + } + case EVAS_3D_MESH_PRIMITIVE_SQUARE: + { + evas_model_set_from_square_primitive(model, frame); + break; + } + case EVAS_3D_MESH_PRIMITIVE_CUBE: + { + evas_model_set_from_cube_primitive(model, frame); + break; + } + case EVAS_3D_MESH_PRIMITIVE_CYLINDER: + { + evas_model_set_from_cylinder_primitive(model, frame, mode, + precision, tex_scale); + break; + } + case EVAS_3D_MESH_PRIMITIVE_CONE: + { + evas_model_set_from_cone_primitive(model, frame, mode, + precision, tex_scale); + break; + } + case EVAS_3D_MESH_PRIMITIVE_SPHERE: + { + evas_model_set_from_sphere_primitive(model, frame, mode, + precision, tex_scale); + break; + } + case EVAS_3D_MESH_PRIMITIVE_TORUS: + { + evas_model_set_from_torus_primitive(model, frame, + ratio, precision, tex_scale); + break; + } + case EVAS_3D_MESH_PRIMITIVE_SURFACE: + { + evas_model_set_from_surface_primitive(model, frame, + surface, precision, tex_scale); + break; + } + case EVAS_3D_MESH_PRIMITIVE_TERRAIN: + { + evas_model_set_from_terrain_primitive(model, frame, + precision, tex_scale); + break; + } + default: + { + ERR("Unknown type of primitive"); + } + } +} diff --git a/src/lib/evas/common3d/primitives/primitive_common.h b/src/lib/evas/common3d/primitives/primitive_common.h new file mode 100644 index 0000000..c2b47f3 --- /dev/null +++ b/src/lib/evas/common3d/primitives/primitive_common.h @@ -0,0 +1,58 @@ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif //HAVE_CONFIG_H + +#ifndef PRIMITIVE_COMMON +#define PRIMITIVE_COMMON +#include "evas_options.h" + +#include "evas_common_private.h" +#include "evas_private.h" + +#define ALLOCATE_VERTEX_DATA \ + Evas_Vec3 *vertices = malloc(sizeof(Evas_Vec3) * vcount); \ + Evas_Vec3 *normals = malloc(sizeof(Evas_Vec3) * vcount); \ + Evas_Vec2 *tex_coord = malloc(sizeof(Evas_Vec2) * vcount); \ + Evas_Vec3 *tangents = malloc(sizeof(Evas_Vec3) * vcount); \ + unsigned short *indices = malloc(sizeof(short) * icount); + +#define SET_VERTEX_DATA(frame) \ + eo_do(mesh, \ + evas_3d_mesh_vertex_count_set(vcount), \ + evas_3d_mesh_frame_add(frame), \ + evas_3d_mesh_index_data_copy_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT, \ + icount, &indices[0])); \ + _set_vec3_vertex_data(mesh, frame, vcount, vertices, EVAS_3D_VERTEX_POSITION); \ + _set_vec3_vertex_data(mesh, frame, vcount, normals, EVAS_3D_VERTEX_NORMAL); \ + _set_vec2_vertex_data(mesh, frame, vcount, tex_coord, EVAS_3D_VERTEX_TEXCOORD); \ + _set_vec3_vertex_data(mesh, frame, vcount, tangents, EVAS_3D_VERTEX_TANGENT); \ + free(indices); + +#define SET_VERTEX_DATA_FROM_ARRAY(mesh, frame, varray, vcount, indices, icount) \ + eo_do(mesh, \ + evas_3d_mesh_vertex_count_set(vcount), \ + evas_3d_mesh_frame_add(frame), \ + evas_3d_mesh_index_data_copy_set(EVAS_3D_INDEX_FORMAT_UNSIGNED_SHORT, \ + icount, &indices[0])); \ + _set_vertex_data_from_array(mesh, frame, varray, EVAS_3D_VERTEX_POSITION, \ + 0, 3, 15, vcount); \ + _set_vertex_data_from_array(mesh, frame, varray, EVAS_3D_VERTEX_NORMAL, \ + 3, 3, 15, vcount); \ + _set_vertex_data_from_array(mesh, frame, varray, EVAS_3D_VERTEX_COLOR, \ + 6, 4, 15, vcount); \ + _set_vertex_data_from_array(mesh, frame, varray, EVAS_3D_VERTEX_TEXCOORD, \ + 10, 2, 15, vcount); \ + _set_vertex_data_from_array(mesh, frame, varray, EVAS_3D_VERTEX_TANGENT, \ + 12, 3, 15, vcount); + +void _generate_indices(unsigned short *indices, int count, int width); +void _set_vec3_vertex_data(Evas_3D_Mesh *mesh, int frame, int vcount, Evas_Vec3 *data, Evas_3D_Vertex_Attrib attr); +void _set_vec2_vertex_data(Evas_3D_Mesh *mesh, int frame, int vcount, Evas_Vec2 *data, Evas_3D_Vertex_Attrib attr); +void _set_vertex_data_from_array(Evas_3D_Mesh *mesh, int frame, const float *data, Evas_3D_Vertex_Attrib attr, int start, int attr_count, int line, int vcount); + +void _primitives_vec3_copy(Evas_Vec3 *dst, const Evas_Vec3 *src); +void _primitives_vec3_subtract(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b); +void _primitives_vec3_cross_product(Evas_Vec3 *out, const Evas_Vec3 *a, const Evas_Vec3 *b); +void _primitives_vec3_normalize(Evas_Vec3 *out); + +#endif //PRIMITIVE_COMMON diff --git a/src/lib/evas/common3d/primitives/solids_of_revolution/cone.c b/src/lib/evas/common3d/primitives/solids_of_revolution/cone.c new file mode 100644 index 0000000..2b62f28 --- /dev/null +++ b/src/lib/evas/common3d/primitives/solids_of_revolution/cone.c @@ -0,0 +1,140 @@ +#include "../primitive_common.h" + +void +_set_default_cone(Evas_3D_Mesh *mesh, + int frame, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i, j, num; + double dfi, fi, sinfi, cosfi, nplane, nz; + + icount = p * 18; + vccount = p + 1; + vcount = 4 * vccount; + + dfi = 2.0 * M_PI / p; + nz = sqrt(1.0 / 3.0); + nplane = sqrt(2.0 / 3.0); + + ALLOCATE_VERTEX_DATA + + for (i = 0; i < vccount; i++) + { + fi = i * dfi; + sinfi = sin(fi); + cosfi = cos(fi); + + vertices[i].x = 0.0; + vertices[i].y = 0.0; + vertices[i].z = -0.5; + vertices[i + vccount].x = sinfi / 2.0; + vertices[i + vccount].y = cosfi / 2.0; + vertices[i + vccount].z = -0.5; + vertices[i + 2 * vccount] = vertices[i + vccount]; + vertices[i + 3 * vccount].x = 0.0; + vertices[i + 3 * vccount].y = 0.0; + vertices[i + 3 * vccount].z = 0.5; + + normals[i].x = normals[i].y = 0.0; + normals[i].z = -1.0; + normals[i + vccount] = normals[i]; + normals[i + 2 * vccount].x = sinfi * nplane; + normals[i + 2 * vccount].y = cosfi * nplane; + normals[i + 2 * vccount].z = nz; + normals[i + 3 * vccount] = normals[i + 2 * vccount]; + + for (j = 0; j < 4; j++) + { + num = i + j * vccount; + + tangents[num].x = cosfi; + tangents[num].y = -sinfi; + tangents[num].z = 0.0; + + tex_coord[num].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[num].y = (float)((j + 1) / 2) * tex_scale.y / 2.0; + } + } + + _generate_indices(indices, p, 3); + + SET_VERTEX_DATA(frame) +} + +void +_set_cone_without_base(Evas_3D_Mesh *mesh, + int frame, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i; + double dfi, fi, sinfi, cosfi, nplane, nz; + + icount = p * 6; + vccount = p + 1; + vcount = 2 * vccount; + + dfi = 2.0 * M_PI / p; + nz = sqrt(1.0 / 3.0); + nplane = sqrt(2.0 / 3.0); + + ALLOCATE_VERTEX_DATA + + for (i = 0; i < vccount; i++) + { + fi = i * dfi; + sinfi = sin(fi); + cosfi = cos(fi); + vertices[i].x = sinfi / 2.0; + vertices[i].y = cosfi / 2.0; + vertices[i].z = -0.5; + vertices[i + vccount].x = 0; + vertices[i + vccount].y = 0; + vertices[i + vccount].z = 0.5; + + normals[i + vccount].x = normals[i].x = sinfi * nplane; + normals[i + vccount].y = normals[i].y = cosfi * nplane; + normals[i + vccount].z = normals[i].z = nz; + + tangents[i + vccount].x = tangents[i].x = cosfi; + tangents[i + vccount].y = tangents[i].y = -sinfi; + tangents[i + vccount].z = tangents[i].z = 0; + + tex_coord[i].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[i].y = 0; + tex_coord[i + vccount].x = tex_coord[i].x; + tex_coord[i + vccount].y = tex_scale.y; + } + + _generate_indices(indices, p, 1); + + SET_VERTEX_DATA(frame) +} + +void +evas_model_set_from_cone_primitive(Evas_3D_Mesh *mesh, + int frame, + Evas_3D_Primitive_Mode mode, + int p, + Evas_Vec2 tex_scale) +{ + switch (mode) + { + case EVAS_3D_PRIMITIVE_MODE_DEFAULT: + case EVAS_3D_PRIMITIVE_MODE_ALTERNATIVE_UV: + { + _set_default_cone(mesh, frame, p, tex_scale); + break; + } + case EVAS_3D_PRIMITIVE_MODE_WITHOUT_BASE: + { + _set_cone_without_base(mesh, frame, p, tex_scale); + break; + } + default: + { + ERR("Unknown mode of primitive"); + } + } +} diff --git a/src/lib/evas/common3d/primitives/solids_of_revolution/cylinder.c b/src/lib/evas/common3d/primitives/solids_of_revolution/cylinder.c new file mode 100644 index 0000000..dabe6f4 --- /dev/null +++ b/src/lib/evas/common3d/primitives/solids_of_revolution/cylinder.c @@ -0,0 +1,136 @@ +#include "../primitive_common.h" + +void +_set_default_cylinder(Evas_3D_Mesh *mesh, + int frame, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i, j, num; + icount = p * 30; + vccount = p + 1; + vcount = 6 * vccount; + + ALLOCATE_VERTEX_DATA + + double dfi, fi, sinfi, cosfi; + dfi = 2 * M_PI / p; + + for (i = 0; i < vccount; i++) + { + fi = i * dfi; + sinfi = sin(fi); + cosfi = cos(fi); + + for (j = 0; j < 6; j++) + { + num = i + j * vccount; + + vertices[num].z = -0.5 + (float)(j / 3); + if ((j == 0) || (j == 5)) + { + vertices[num].x = vertices[num].y = 0.0; + } + else + { + vertices[num].x = sinfi / 2.0; + vertices[num].y = cosfi / 2.0; + } + + if ((j == 2) || (j == 3)) + { + normals[num].x = sinfi; + normals[num].y = cosfi; + normals[num].z = 0.0; + } + else + { + normals[num].x = normals[num].y = 0.0; + normals[num].z = -1.0 + (float)(j / 2); + } + + tangents[num].x = cosfi; + tangents[num].y = -sinfi; + tangents[num].z = 0.0; + + tex_coord[num].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[num].y = (float)((j + 1) / 2) * tex_scale.y / 3.0; + } + } + + _generate_indices(indices, p, 5); + + SET_VERTEX_DATA(frame) +} + +void +_set_cylinder_without_bases(Evas_3D_Mesh *mesh, + int frame, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i; + icount = p * 6; + vccount = p + 1; + vcount = 2 * vccount; + + ALLOCATE_VERTEX_DATA + + double dfi, fi, sinfi, cosfi; + dfi = 2 * M_PI / p; + + for (i = 0; i < vccount; i++) + { + fi = i * dfi; + sinfi = sin(fi); + cosfi = cos(fi); + vertices[i + vccount].x = vertices[i].x = sinfi / 2.0; + vertices[i + vccount].y = vertices[i].y = cosfi / 2.0; + vertices[i].z = -0.5; + vertices[i + vccount].z = 0.5; + + normals[i + vccount].x = normals[i].x = sinfi; + normals[i + vccount].y = normals[i].y = cosfi; + normals[i + vccount].z = normals[i].z = 0; + + tangents[i + vccount].x = tangents[i].x = cosfi; + tangents[i + vccount].y = tangents[i].y = -sinfi; + tangents[i + vccount].z = tangents[i].z = 0; + + tex_coord[i].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[i].y = 0; + tex_coord[i + vccount].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[i + vccount].y = tex_scale.y; + } + + _generate_indices(indices, p, 1); + + SET_VERTEX_DATA(frame) +} + +void +evas_model_set_from_cylinder_primitive(Evas_3D_Mesh *mesh, + int frame, + Evas_3D_Primitive_Mode mode, + int p, + Evas_Vec2 tex_scale) +{ + switch (mode) + { + case EVAS_3D_PRIMITIVE_MODE_DEFAULT: + case EVAS_3D_PRIMITIVE_MODE_ALTERNATIVE_UV: + { + _set_default_cylinder(mesh, frame, p, tex_scale); + break; + } + case EVAS_3D_PRIMITIVE_MODE_WITHOUT_BASE: + { + _set_cylinder_without_bases(mesh, frame, p, tex_scale); + break; + } + default: + { + ERR("Unknown mode of primitive"); + } + } +} diff --git a/src/lib/evas/common3d/primitives/solids_of_revolution/sphere.c b/src/lib/evas/common3d/primitives/solids_of_revolution/sphere.c new file mode 100644 index 0000000..1a2409b --- /dev/null +++ b/src/lib/evas/common3d/primitives/solids_of_revolution/sphere.c @@ -0,0 +1,189 @@ +#include "../primitive_common.h" + +void +_set_default_sphere(Evas_3D_Mesh *mesh, + int frame, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i, j; + icount = p * p * 6; + vccount = p + 1; + vcount = vccount * vccount; + + ALLOCATE_VERTEX_DATA + + double dtheta, dfi, sinth, costh, fi, theta, sinfi, cosfi; + dtheta = M_PI / p; + dfi = 2 * M_PI / p; + + for (j = 0; j < vccount; j++) + { + theta = j * dtheta; + sinth = sin(theta); + costh = cos(theta); + for (i = 0; i < vccount; i++) + { + fi = i * dfi; + sinfi = sin(fi); + cosfi = cos(fi); + normals[i + j * vccount].x = sinth * sinfi; + normals[i + j * vccount].y = sinth * cosfi; + normals[i + j * vccount].z = costh; + + vertices[i + j * vccount].x = normals[i + j * vccount].x / 2; + vertices[i + j * vccount].y = normals[i + j * vccount].y / 2; + vertices[i + j * vccount].z = normals[i + j * vccount].z / 2; + + tangents[i + j * vccount].x = -sinth * cosfi; + tangents[i + j * vccount].y = sinth * sinfi; + tangents[i + j * vccount].z = 0; + + _primitives_vec3_normalize(&tangents[i + j * vccount]); + + tex_coord[i + j * vccount].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[i + j *vccount].y = tex_scale.y - j / (float)(vccount - 1) * tex_scale.y; + } + } + + _generate_indices(indices, p, p); + + SET_VERTEX_DATA(frame) +} + +void +_set_sphere_with_alternative_uv(Evas_3D_Mesh *mesh, + int frame, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i, j; + + vccount = p + 1; + vcount = vccount * vccount; + icount = p * p * 6; + + ALLOCATE_VERTEX_DATA + + /* Calculate vertices position of the sphere mesh by using + splitting of sphere by latitude and longitude. */ + for (i = 0; i <= p; i++) + { + double lati, z, r, point_r; + + point_r = 0.00001;//non-zero little value for correct tangents calculation. + + lati = ((M_PI - 2 * point_r) * (double)i) / (double)p; + z = cos(lati + point_r); + r = fabs(sin(lati + point_r)); + + for (j = 0; j <= p; j++) + { + double longi; + int num = (i * (p + 1)) + j; + + longi = (M_PI * 2.0 * (double)j) / (double)p; + + normals[num].x = r * sin(longi); + normals[num].y = r * cos(longi); + normals[num].z = z; + + vertices[num].x = normals[num].x / 2; + vertices[num].y = normals[num].y / 2; + vertices[num].z = normals[num].z / 2; + + if (vertices[num].x > 0.0) + { + tangents[num].x = -normals[num].z; + tangents[num].y = normals[num].y; + tangents[num].z = normals[num].x; + } + else + { + tangents[num].x = normals[num].z; + tangents[num].y = normals[num].y; + tangents[num].z = -normals[num].x; + } + + tex_coord[num].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[num].y = tex_scale.y - j / (float)(vccount - 1) * tex_scale.y; + } + } + + _generate_indices(indices, p, p); + + /* Triangulation of sphere mesh in appliance with buffer of indices. */ + for (i = 0; i < icount; i += 3) + { + Evas_Vec3 e1, e2; + float du1, du2, dv1, dv2, f; + Evas_Vec3 tangent; + int num0, num1, num2; + + num0 = indices[i + 0]; + num1 = indices[i + 1]; + num2 = indices[i + 2]; + + e1.x = vertices[num1].x - vertices[num0].x; + e1.y = vertices[num1].y - vertices[num0].y; + e1.z = vertices[num1].z - vertices[num0].z; + + e2.x = vertices[num2].x - vertices[num0].x; + e2.y = vertices[num2].y - vertices[num0].y; + e2.z = vertices[num2].z - vertices[num0].z; + + du1 = tex_coord[num1].x - tex_coord[num0].x; + dv1 = tex_coord[num1].y - tex_coord[num0].y; + + du2 = tex_coord[num2].x - tex_coord[num0].x; + dv2 = tex_coord[num2].y - tex_coord[num0].y; + + f = 1.0 / ((du1 * dv2) - (du2 * dv1)); + + tangent.x = f * ((dv2 * e1.x) - (dv1 * e2.x)); + tangent.y = f * ((dv2 * e1.y) - (dv1 * e2.y)); + tangent.z = f * ((dv2 * e1.z) - (dv1 * e2.z)); + + tangents[num0] = tangent; + } + + /* Coupling between vertices by calculation of tangent parametr correct value. */ + for (i = 0; i <= p; i++) + { + for (j = 0; j <= p; j++) + { + if (j == p) + { + tangents[(i * (p + 1)) + j] = tangents[i * (p + 1)]; + } + } + } + SET_VERTEX_DATA(frame) +} + +void +evas_model_set_from_sphere_primitive(Evas_3D_Mesh *mesh, + int frame, + Evas_3D_Primitive_Mode mode, + int p, + Evas_Vec2 tex_scale) +{ + switch (mode) + { + case EVAS_3D_PRIMITIVE_MODE_DEFAULT: + case EVAS_3D_PRIMITIVE_MODE_WITHOUT_BASE: + { + _set_default_sphere(mesh, frame, p, tex_scale); + break; + } + case EVAS_3D_PRIMITIVE_MODE_ALTERNATIVE_UV: + { + _set_sphere_with_alternative_uv(mesh, frame, p, tex_scale); + break; + } + default: + { + ERR("Unknown mode of primitive"); + } + } +} diff --git a/src/lib/evas/common3d/primitives/solids_of_revolution/torus.c b/src/lib/evas/common3d/primitives/solids_of_revolution/torus.c new file mode 100644 index 0000000..abb76d8 --- /dev/null +++ b/src/lib/evas/common3d/primitives/solids_of_revolution/torus.c @@ -0,0 +1,67 @@ +#include "../primitive_common.h" + +void +evas_model_set_from_torus_primitive(Evas_3D_Mesh *mesh, + int frame, + Evas_Real ratio, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i, j; + icount = p * p * 6; + vccount = p + 1; + vcount = vccount * vccount; + + ALLOCATE_VERTEX_DATA + + double d, sinth, costh, fi, theta, sinfi, cosfi; + + d = 2 * M_PI / p; + + float rratio; + + if ((ratio < 1.0)) + { + printf("Ratio of torus should be greater than or equal 1.0.\n"); + printf("Ratio = %f is a bad value, so 3.0 is used like default ratio.\n", + ratio); + rratio = 1.0 / 3.0; + } + else + { + rratio = 1.0 / ratio; + } + + for (j = 0; j < vccount; j++) + { + theta = j * d; + sinth = sin(theta); + costh = cos(theta); + for (i = 0; i < vccount; i++) + { + fi = i * d; + sinfi = sin(fi); + cosfi = cos(fi); + vertices[i + j * vccount].x = (1.0 - rratio + rratio * cosfi) * costh * 0.5; + vertices[i + j * vccount].y = (1.0 - rratio + rratio * cosfi) * sinth * 0.5; + vertices[i + j * vccount].z = rratio * sinfi * 0.5; + + normals[i + j * vccount].x = cosfi * costh; + normals[i + j * vccount].y = cosfi * sinth; + normals[i + j * vccount].z = sinfi; + + tangents[i + j * vccount].x = -sinfi * costh; + tangents[i + j * vccount].y = -sinfi * sinth; + tangents[i + j * vccount].z = cosfi; + + _primitives_vec3_normalize(&normals[i + j * vccount]); + + tex_coord[i + j * vccount].x = i / (float)(vccount - 1) * tex_scale.x; + tex_coord[i + j *vccount].y = tex_scale.y - j / (float)(vccount - 1) * tex_scale.y; + } + } + + _generate_indices(indices, p, p); + + SET_VERTEX_DATA(frame) +} diff --git a/src/lib/evas/common3d/primitives/surfaces/surface.c b/src/lib/evas/common3d/primitives/surfaces/surface.c new file mode 100644 index 0000000..7eb1779 --- /dev/null +++ b/src/lib/evas/common3d/primitives/surfaces/surface.c @@ -0,0 +1,91 @@ +#include "../primitive_common.h" + +Evas_Vec3 _get_func_normal(Evas_3D_Surface_Func *func, Evas_Real x, Evas_Real y) +{ + Evas_Vec3 v00, v01, v10, d1, d2, normal; + + func(&v00.x, &v00.y, &v00.z, x, y); + func(&v01.x, &v01.y, &v01.z, x, y + 0.01); + func(&v10.x, &v10.y, &v10.z, x + 0.01, y); + _primitives_vec3_subtract(&d1, &v00, &v01); + _primitives_vec3_subtract(&d2, &v01, &v10); + + _primitives_vec3_cross_product(&normal, &d1, &d2); + + _primitives_vec3_normalize(&normal); + + return normal; +} + +void +_normalize(Evas_Vec3 *vertices, Evas_Vec3 *normals, int vcount) +{ + int i; + Evas_Vec3 min, max; + min = max = vertices[0]; + +#define CHECK_MIN_AND_MAX(coord) \ + if (min.coord > vertices[i].coord) \ + min.coord = vertices[i].coord; \ + else if (max.coord < vertices[i].coord) \ + max.coord = vertices[i].coord; + for (i = 1; i < vcount; i++) + { + CHECK_MIN_AND_MAX(x) + CHECK_MIN_AND_MAX(y) + CHECK_MIN_AND_MAX(z) + } +#undef CHECK_MIN_AND_MAX + + for (i = 0; i < vcount; i++) + { + vertices[i].x = (vertices[i].x - min.x) / (max.x - min.x) - 0.5; + vertices[i].y = (vertices[i].y - min.y) / (max.y - min.y) - 0.5; + vertices[i].z = (vertices[i].z - min.z) / (max.z - min.z) - 0.5; + + normals[i].x = normals[i].x / (max.x - min.x); + normals[i].y = normals[i].y / (max.y - min.y); + normals[i].z = normals[i].z / (max.z - min.z); + } +} + +void +evas_model_set_from_surface_primitive(Evas_3D_Mesh *mesh, + int frame, + Evas_3D_Surface_Func func, + int p, + Evas_Vec2 tex_scale) +{ + int vcount, icount, vccount, i, j, num; + icount = p * p * 6; + vccount = p + 1; + vcount = vccount * vccount; + + ALLOCATE_VERTEX_DATA + + Evas_Real v, u, d = 1.0 / p; + + for (j = 0; j < vccount; j++) + { + u = j * d - 0.5; + for (i = 0; i < vccount; i++) + { + v = i * d - 0.5; + num = i + j * vccount; + func(&vertices[num].x, + &vertices[num].y, + &vertices[num].z, + v, u); + normals[num] = _get_func_normal(func, v, u); + + tangents[num].x = tangents[num].y = tangents[num].z = 0; + + tex_coord[num].x = i / ((vccount - 1) * tex_scale.x); + tex_coord[num].y = tex_scale.y - j / ((vccount - 1) * tex_scale.y); + } + } + + _normalize(vertices, normals, vcount); + _generate_indices(indices, p, p); + SET_VERTEX_DATA(frame) +} diff --git a/src/lib/evas/common3d/primitives/surfaces/terrain.c b/src/lib/evas/common3d/primitives/surfaces/terrain.c new file mode 100644 index 0000000..542ed74 --- /dev/null +++ b/src/lib/evas/common3d/primitives/surfaces/terrain.c @@ -0,0 +1,86 @@ +#include "../primitive_common.h" + +static Evas_Real +_random(int x, int y) +{ + int k = x + y * 57; + k = (k << 13) ^ k; + return (1.0f - ((k * (k * k * 15731 + 789221) + 1376312589) & 0x7fffffff) / + 1073741824.0f); +} + +static Evas_Real +_smooth(Evas_Real x, Evas_Real y) +{ + Evas_Real res; + res = (_random(x - 1, y - 1) + _random(x + 1, y - 1) + + _random(x - 1, y + 1) + _random(x + 1, y + 1)) / 16; + res += (_random(x - 1, y) + _random(x + 1, y) + + _random(x, y - 1) + _random(x, y + 1)) / 8; + res += _random(x, y) / 4; + return res; +} + +static Evas_Real +_interpolate(Evas_Real a, Evas_Real b, Evas_Real x) +{ + Evas_Real ft = x * M_PI; + Evas_Real f = (1 - cosf(ft)) * 0.5; + return a * (1 - f) + b * f; +} + +static Evas_Real _noise(Evas_Real x, Evas_Real y) +{ + Evas_Real ix = (int)(x); + Evas_Real fx = x - ix; + Evas_Real iy = (int)(y); + Evas_Real fy = y - iy; + + Evas_Real v1 = _smooth(ix, iy); + Evas_Real v2 = _smooth(ix + 1, iy); + Evas_Real v3 = _smooth(ix, iy + 1); + Evas_Real v4 = _smooth(ix + 1, iy + 1); + + Evas_Real i1 = _interpolate(v1, v2, fx); + Evas_Real i2 = _interpolate(v3, v4, fx); + + return _interpolate(i1, i2, fy); +} + +static void +_perlin_terrain(Evas_Real *out_x, + Evas_Real *out_y, + Evas_Real *out_z, + Evas_Real x, + Evas_Real y) +{ + Evas_Real persistence = 0.5f; + Evas_Real frequency = 5; + Evas_Real amplitude = 1; + int i = 0; + int octaves = 5; + + *out_x = x; + x += 0.5; + *out_y = y; + y += 0.5; + *out_z = 0; + + for(i = 0; i < octaves; i++) + { + *out_z += _noise(x * frequency, y * frequency) * amplitude; + + amplitude *= persistence; + frequency *= 2; + } +} + +void +evas_model_set_from_terrain_primitive(Evas_3D_Mesh *mesh, + int frame, + int p, + Evas_Vec2 tex_scale) +{ + evas_model_set_from_surface_primitive(mesh, frame, _perlin_terrain, p, tex_scale); +} + diff --git a/src/lib/evas/common3d/primitives/tabulated_primitives/cube.c b/src/lib/evas/common3d/primitives/tabulated_primitives/cube.c new file mode 100644 index 0000000..6f70a02 --- /dev/null +++ b/src/lib/evas/common3d/primitives/tabulated_primitives/cube.c @@ -0,0 +1,57 @@ +#include "../primitive_common.h" + +const float vertices_of_cube[] = +{ + /* positions normals vertex_color tex_coords tangents */ + /* Front */ + 0.5, -0.5, 0.5, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, + -0.5, -0.5, 0.5, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, + -0.5, -0.5, -0.5, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, -1.0, 0.0, 0.0, + 0.5, -0.5, -0.5, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, 0.0, + + /* Left */ + -0.5, -0.5, 0.5, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 1.0, + -0.5, 0.5, 0.5, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 1.0, + -0.5, 0.5, -0.5, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 1.0, + -0.5, -0.5, -0.5, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, + + /* Back */ + -0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, + 0.5, 0.5, 0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, + 0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, + -0.5, 0.5, -0.5, 0.0, 1.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, + + /* Right */ + 0.5, 0.5, 0.5, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, -1.0, + 0.5, -0.5, 0.5, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, -1.0, + 0.5, -0.5, -0.5, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, -1.0, + 0.5, 0.5, -0.5, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, -1.0, + + /* Top */ + -0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, + -0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, + 0.5, 0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, + 0.5, -0.5, 0.5, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, + + /* Bottom */ + -0.5, -0.5, -0.5, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, -1.0, 0.0, 0.0, + -0.5, 0.5, -0.5, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, -1.0, 0.0, 0.0, + 0.5, 0.5, -0.5, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, -1.0, 0.0, 0.0, + 0.5, -0.5, -0.5, 0.0, 0.0, -1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, -1.0, 0.0, 0.0, +}; + +const unsigned short indices_of_cube[] = +{ + 0, 1, 2, 6, 7, 4, + 4, 5, 6, 10, 11, 8, + 8, 9, 10, 14, 15, 12, + 12, 13, 14, 2, 3, 0, + 19, 16, 17, 17, 18, 19, + 23, 20, 21, 21, 22, 23 +}; + +void +evas_model_set_from_cube_primitive(Evas_3D_Mesh *mesh, int frame) +{ + SET_VERTEX_DATA_FROM_ARRAY(mesh, frame, vertices_of_cube, 24, indices_of_cube, 36) +} diff --git a/src/lib/evas/common3d/primitives/tabulated_primitives/square.c b/src/lib/evas/common3d/primitives/tabulated_primitives/square.c new file mode 100644 index 0000000..6f5c0c6 --- /dev/null +++ b/src/lib/evas/common3d/primitives/tabulated_primitives/square.c @@ -0,0 +1,18 @@ +#include "../primitive_common.h" + +const float vertices_of_square[] = +{ + /* positions normals vertex_color tex_coords tangents */ + -0.5, 0.5, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 1.0, 1.0, 0.0, 0.0, + 0.5, 0.5, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 0.0, 0.0, + -0.5, -0.5, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, 1.0, 0.0, 0.0, + 0.5, -0.5, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0, 1.0, 1.0, 0.0, 1.0, 0.0, 0.0, +}; + +const unsigned short indices_of_square[] = {0, 1, 2, 2, 1, 3}; + +void +evas_model_set_from_square_primitive(Evas_3D_Mesh *mesh, int frame) +{ + SET_VERTEX_DATA_FROM_ARRAY(mesh, frame, vertices_of_square, 4, indices_of_square, 6) +} diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 7d9303c..e7c8d02 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -100,6 +100,7 @@ typedef struct _Evas_3D_Camera Evas_3D_Camera_Data; typedef struct _Evas_3D_Light Evas_3D_Light_Data; typedef struct _Evas_3D_Material Evas_3D_Material_Data; typedef struct _Evas_3D_Texture Evas_3D_Texture_Data; +typedef struct _Evas_3D_Primitive Evas_3D_Primitive_Data; /* Structs for mesh eet saver/loader */ typedef struct _Evas_3D_Vec2_Eet Evas_3D_Vec2_Eet; @@ -415,6 +416,17 @@ struct _Evas_3D_Material Eina_Hash *meshes; }; +struct _Evas_3D_Primitive +{ + Evas_3D_Mesh_Primitive form; + Evas_3D_Primitive_Mode mode; + Evas_Real ratio; + int precision; + Evas_3D_Surface_Func *surface; + + Evas_Vec2 tex_scale; +}; + struct _Evas_3D_Scene_Public_Data { Evas_Color bg_color; @@ -1746,6 +1758,17 @@ void evas_model_save_file_eet(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh void evas_model_save_file_obj(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh_Frame *f); void evas_model_save_file_ply(Evas_3D_Mesh *mesh, const char *file, Evas_3D_Mesh_Frame *f); +/* Primitives functions */ +void evas_common_set_model_from_primitive(Evas_3D_Mesh *model, int frame, Evas_3D_Primitive_Data *primitive); +void evas_model_set_from_square_primitive(Evas_3D_Mesh *mesh, int frame); +void evas_model_set_from_cube_primitive(Evas_3D_Mesh *mesh, int frame); +void evas_model_set_from_cylinder_primitive(Evas_3D_Mesh *mesh, int frame, Evas_3D_Primitive_Mode mode, int precision, Evas_Vec2 tex_scale); +void evas_model_set_from_cone_primitive(Evas_3D_Mesh *mesh, int frame, Evas_3D_Primitive_Mode mode, int precision, Evas_Vec2 tex_scale); +void evas_model_set_from_sphere_primitive(Evas_3D_Mesh *mesh, int frame, Evas_3D_Primitive_Mode mode, int precision, Evas_Vec2 tex_scale); +void evas_model_set_from_torus_primitive(Evas_3D_Mesh *mesh, int frame, Evas_Real ratio, int precision, Evas_Vec2 tex_scale); +void evas_model_set_from_surface_primitive(Evas_3D_Mesh *mesh, int frame, Evas_3D_Surface_Func func, int precision, Evas_Vec2 tex_scale); +void evas_model_set_from_terrain_primitive(Evas_3D_Mesh *mesh, int frame, int precision, Evas_Vec2 tex_scale); + extern int _evas_alloc_error; extern int _evas_event_counter; --