summaryrefslogtreecommitdiff
path: root/src/lib/evas/common3d/primitives/surfaces/surface.c
blob: 7698ba5fb6d4640d9343912176c2f3f2ba5b5a6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "../primitive_common.h"

Eina_Vector3 _get_func_normal(Evas_Canvas3D_Surface_Func *func, Evas_Real x, Evas_Real y)
{
   Eina_Vector3 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(Eina_Vector3 *vertices, Eina_Vector3 *normals, int vcount)
{
   int i;
   Eina_Vector3 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_Canvas3D_Mesh *mesh,
                                      int frame,
                                      Evas_Canvas3D_Surface_Func func,
                                      int p,
                                      Eina_Vector2 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)
}