summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBogdan Devichev <b.devichev@samsung.com>2015-05-26 18:49:15 +0200
committerCedric BAIL <cedric@osg.samsung.com>2015-05-27 00:31:07 +0200
commit6dac83e643934573a734491d97b549a6b235c0f5 (patch)
treea5272df551b3c77107e79910cb0f9bde2f8ca6cc /src
parentabc1eabecb6da1bf77b530132814a2427bfb44fb (diff)
downloadefl-6dac83e643934573a734491d97b549a6b235c0f5.tar.gz
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 <cedric@osg.samsung.com>
Diffstat (limited to 'src')
-rw-r--r--src/Makefile_Evas.am14
-rw-r--r--src/lib/evas/Evas_Eo.h61
-rw-r--r--src/lib/evas/canvas/evas_3d_mesh.c13
-rw-r--r--src/lib/evas/canvas/evas_3d_mesh.eo11
-rw-r--r--src/lib/evas/canvas/evas_3d_primitive.c162
-rw-r--r--src/lib/evas/canvas/evas_3d_primitive.eo179
-rw-r--r--src/lib/evas/common3d/primitives/primitive_common.c209
-rw-r--r--src/lib/evas/common3d/primitives/primitive_common.h58
-rw-r--r--src/lib/evas/common3d/primitives/solids_of_revolution/cone.c140
-rw-r--r--src/lib/evas/common3d/primitives/solids_of_revolution/cylinder.c136
-rw-r--r--src/lib/evas/common3d/primitives/solids_of_revolution/sphere.c189
-rw-r--r--src/lib/evas/common3d/primitives/solids_of_revolution/torus.c67
-rw-r--r--src/lib/evas/common3d/primitives/surfaces/surface.c91
-rw-r--r--src/lib/evas/common3d/primitives/surfaces/terrain.c86
-rw-r--r--src/lib/evas/common3d/primitives/tabulated_primitives/cube.c57
-rw-r--r--src/lib/evas/common3d/primitives/tabulated_primitives/square.c18
-rw-r--r--src/lib/evas/include/evas_private.h23
17 files changed, 1511 insertions, 3 deletions
diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am
index 72f8365348..3a2f4af055 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 c81ce469d2..e401a51578 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 1b8cc14eb9..f15b42fc4f 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 5789cc00cb..db0f895df4 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 0000000000..34ecab6aef
--- /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 0000000000..e1336c66c0
--- /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 0000000000..066ef3b35c
--- /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 0000000000..c2b47f375b
--- /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 0000000000..2b62f287c0
--- /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 0000000000..dabe6f4989
--- /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 0000000000..1a2409b2a5
--- /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 0000000000..abb76d8c88
--- /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 0000000000..7eb1779ebe
--- /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 0000000000..542ed74b0d
--- /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 0000000000..6f70a02b9d
--- /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 0000000000..6f5c0c6f27
--- /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 7d9303c802..e7c8d02a5d 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;