summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorperepelits.m <perepelits.m@samsung.com>2015-07-29 22:24:02 +0200
committerCedric BAIL <cedric@osg.samsung.com>2015-08-04 17:34:29 +0200
commitbe33840b6b703f2b1e64c8e4788f968ad8c7f87b (patch)
tree4a94d9a2ea7a4b534071965a3b8c08d487a5e884
parent10fb77cc558672ebe6ae2d60fa085837c6b97320 (diff)
evas: add tangent space algorithm
Summary: This is a logic of tangent data calculation, we need it in order to avoid bugs with normal mapping after building with opengl=yes. Reviewers: Hermet, raster, cedric Reviewed By: cedric Subscribers: Oleksander, cedric, artem.popov Differential Revision: https://phab.enlightenment.org/D2802 Signed-off-by: Cedric BAIL <cedric@osg.samsung.com>
-rw-r--r--src/lib/evas/include/evas_3d_utils.h223
1 files changed, 223 insertions, 0 deletions
diff --git a/src/lib/evas/include/evas_3d_utils.h b/src/lib/evas/include/evas_3d_utils.h
index bd6aaa60ac..3239e3e76c 100644
--- a/src/lib/evas/include/evas_3d_utils.h
+++ b/src/lib/evas/include/evas_3d_utils.h
@@ -439,6 +439,22 @@ evas_vec3_quaternion_rotate(Evas_Vec3 *out, const Evas_Vec3 *v, const Evas_Vec4
439 out->z = v->z + uv.z + uuv.z; 439 out->z = v->z + uv.z + uuv.z;
440} 440}
441 441
442static inline void
443evas_vec3_orthogonal_projection_on_plain(Evas_Vec3 *out, const Evas_Vec3 *v, const Evas_Vec3 *normal)
444{
445 Evas_Real a;
446 Evas_Vec3 projection;
447
448 /* Orthoprojection of vector on the plane is the difference
449 between a vector and its orthogonal projection onto the orthogonal
450 complement to the plane */
451 a = evas_vec3_dot_product(v, normal) / evas_vec3_length_square_get(normal);
452 evas_vec3_scale(&projection, normal, a);
453 evas_vec3_subtract(out, v, &projection);
454
455 return;
456}
457
442/* 4D vector */ 458/* 4D vector */
443static inline void 459static inline void
444evas_vec4_set(Evas_Vec4 *dst, Evas_Real x, Evas_Real y, Evas_Real z, Evas_Real w) 460evas_vec4_set(Evas_Vec4 *dst, Evas_Real x, Evas_Real y, Evas_Real z, Evas_Real w)
@@ -2157,6 +2173,46 @@ box_intersection_box(Evas_Box3 *v1, Evas_Box3 *v2)
2157} 2173}
2158 2174
2159static inline void 2175static inline void
2176tangent_new_basis(Evas_Vec3 *out, Evas_Triangle3 *triangle,
2177 Evas_Vec2 *a, Evas_Vec2 *b, Evas_Vec2 *c)
2178{
2179 Evas_Vec2 new1, new2;
2180 Evas_Vec3 old1, old2;
2181 evas_vec3_set(out, 0, 0, 0);
2182
2183 evas_vec2_subtract(&new1, b, a);
2184 evas_vec2_subtract(&new2, c, a);
2185 evas_vec3_subtract(&old1, &(triangle->p1), &(triangle->p0));
2186 evas_vec3_subtract(&old2, &(triangle->p2), &(triangle->p0));
2187
2188
2189 /* calculation of new basis(in system coordinates of texturing) by solution of system of equations */
2190 if (new2.y != 0)
2191 {
2192 evas_vec3_scale(&old2, &old2, (new1.y / new2.y));
2193 evas_vec2_scale(&new2, &new2, (new1.y / new2.y));
2194
2195 evas_vec2_subtract(&new1, &new1, &new2);
2196 evas_vec3_subtract(&old1, &old1, &old2);
2197
2198 evas_vec3_scale(out, &old1, 1 / new1.x);
2199 }
2200
2201 else if (new1.y != 0)
2202 {
2203 evas_vec3_scale(&old1, &old1, (new2.y / new1.y));
2204 evas_vec2_scale(&new1, &new1, (new2.y / new1.y));
2205
2206 evas_vec2_subtract(&new2, &new2, &new1);
2207 evas_vec3_subtract(&old2, &old2, &old1);
2208
2209 evas_vec3_scale(out, &old2, 1 / new2.x);
2210 }
2211
2212 return;
2213}
2214
2215static inline void
2160convex_hull_vertex_set(Evas_Triangle3 *el, int *vertex_count, float **vertex, 2216convex_hull_vertex_set(Evas_Triangle3 *el, int *vertex_count, float **vertex,
2161 unsigned short int **index, unsigned int k, int *leader, int coord) 2217 unsigned short int **index, unsigned int k, int *leader, int coord)
2162{ 2218{
@@ -2716,3 +2772,170 @@ evas_convex_hull_get(float *data, int count, int stride, float **vertex,
2716 2772
2717 return; 2773 return;
2718} 2774}
2775
2776static inline void
2777tangent_space_weighted_sum(Evas_Vec3 *big_t, Evas_Vec3 *little_t,
2778 Evas_Real *big_angle, Evas_Real little_angle)
2779{
2780 /* one way to calculate tangent in vertex that is found in many triangles */
2781 evas_vec3_scale(big_t, big_t, *big_angle / (*big_angle + little_angle));
2782 evas_vec3_scale(little_t, little_t, little_angle / (*big_angle + little_angle));
2783 evas_vec3_add(big_t, big_t, little_t);
2784 *big_angle += little_angle;
2785 return;
2786}
2787
2788
2789static inline Evas_Real
2790tangent_space_triangle_angle_get(Evas_Vec3 *first, Evas_Vec3 *second, Evas_Vec3 *third)
2791{
2792 Evas_Vec3 a, b, c;
2793 Evas_Real cos, arccos;
2794
2795 evas_vec3_subtract(&a, second, third);
2796 evas_vec3_subtract(&b, third, first);
2797 evas_vec3_subtract(&c, first, second);
2798
2799 cos = -(evas_vec3_length_square_get(&a) - evas_vec3_length_square_get(&b) -
2800 evas_vec3_length_square_get(&c)) / (2 * evas_vec3_length_get(&b) *
2801 evas_vec3_length_get(&c));
2802 arccos = acos(cos);
2803
2804 return arccos;
2805}
2806
2807static inline void
2808evas_tangent_space_get(float *data, float *tex_data, float *normal_data, unsigned short int *index, int vertex_count,
2809 int index_count, int stride, int tex_stride, int normal_stride, float **tangent)
2810{
2811 Eina_Bool if_not_primitive = EINA_FALSE;
2812 Evas_Real big_angle, little_angle;
2813 Evas_Triangle3 triangle;
2814 Evas_Vec2 tex1, tex2, tex3;
2815 Evas_Vec3 big_tangent, little_tangent, normal;
2816 Evas_Vec4 *plain = NULL;
2817 int i, j, k, l, m, found_index = NULL;
2818 int indexes[3];
2819
2820 if (!tex_data)
2821 {
2822 ERR("Impossible to calculate tangent space, texture coordinates not found %d %s", __LINE__, __FILE__);
2823 return;
2824 }
2825
2826 if (!(*tangent))
2827 {
2828 ERR("Failed to allocate memory %d %s", __LINE__, __FILE__);
2829 return;
2830 }
2831
2832 unsigned short int *tmp_index = (unsigned short int*) malloc((vertex_count) * sizeof(unsigned short int));
2833
2834 if (tmp_index == NULL)
2835 {
2836 ERR("Failed to allocate memory %d %s", __LINE__, __FILE__);
2837 return;
2838 }
2839
2840 float *tmp_tangent = (float*) malloc((3 * vertex_count) * sizeof(float));
2841 if (tmp_tangent == NULL)
2842 {
2843 ERR("Failed to allocate memory %d %s", __LINE__, __FILE__);
2844 return;
2845 }
2846
2847 if (index_count == 0)
2848 {
2849 if_not_primitive = EINA_TRUE;
2850 index_count = vertex_count;
2851 }
2852
2853 for (i = 0, j = 0, k = 0; i < vertex_count; i++, j += stride, k += normal_stride)
2854 {
2855 evas_vec3_set(&big_tangent, 0.0, 0.0, 0.0);
2856 big_angle = 0.0;
2857 for (l = 0, m = 0; l < vertex_count; l++, m += stride)
2858 {
2859 /* tangent for vertex is calculating in each triangle in which the vertex is found */
2860 if ((fabs(data[j] - data[m]) < FLT_EPSILON) &&
2861 (fabs(data[j + 1] - data[m + 1]) < FLT_EPSILON) &&
2862 (fabs(data[j + 2] - data[m + 2]) < FLT_EPSILON) &&
2863 ((m == j) || ((tex_data[i * tex_stride] != 0.0) && (tex_data[i * tex_stride + 1] != 0.0) &&
2864 (tex_data[i * tex_stride] != 1.0) && (tex_data[i * tex_stride + 1] != 1.0))))
2865 {
2866 found_index = l;
2867 for (k = 0; k < index_count; k += 3)
2868 {
2869 /* there is no index count and indexes , for models that are not a primitive,
2870 so we use the vertex count and an ordered array instead of them */
2871 if (if_not_primitive)
2872 {
2873 indexes[0] = k;
2874 indexes[1] = k + 1;
2875 indexes[2] = k + 2;
2876 }
2877 else
2878 {
2879 indexes[0] = index[k];
2880 indexes[1] = index[k + 1];
2881 indexes[2] = index[k + 2];
2882 }
2883
2884 if ((found_index == indexes[0]) ||
2885 (found_index == indexes[1]) ||
2886 (found_index == indexes[2]))
2887 {
2888 evas_vec3_set(&triangle.p0, data[indexes[0] * stride], data[indexes[0] * stride + 1], data[indexes[0] * stride + 2]);
2889 evas_vec3_set(&triangle.p1, data[indexes[1] * stride], data[indexes[1] * stride + 1], data[indexes[1] * stride + 2]);
2890 evas_vec3_set(&triangle.p2, data[indexes[2] * stride], data[indexes[2] * stride + 1], data[indexes[2] * stride + 2]);
2891 if (plain)
2892 free(plain);
2893 plain = malloc(sizeof(Evas_Vec4));
2894
2895 evas_vec4_plain_by_points(plain, &triangle.p0, &triangle.p1, &triangle.p2);
2896 tex1.x = tex_data[indexes[0] * tex_stride];
2897 tex1.y = tex_data[indexes[0] * tex_stride + 1];
2898 tex2.x = tex_data[indexes[1] * tex_stride];
2899 tex2.y = tex_data[indexes[1] * tex_stride + 1];
2900 tex3.x = tex_data[indexes[2] * tex_stride];
2901 tex3.y = tex_data[indexes[2] * tex_stride + 1];
2902
2903 /* calculate the tangent */
2904 tangent_new_basis(&little_tangent, &triangle,
2905 &tex1, &tex2, &tex3);
2906 evas_vec3_normalize(&little_tangent, &little_tangent);
2907
2908 /* founding the angle in triangle in founded vertex */
2909 if (found_index == indexes[0])
2910 little_angle = tangent_space_triangle_angle_get(&triangle.p0, &triangle.p1, &triangle.p2);
2911
2912 else if (found_index == indexes[1])
2913 little_angle = tangent_space_triangle_angle_get(&triangle.p1, &triangle.p0, &triangle.p2);
2914
2915 else
2916 little_angle = tangent_space_triangle_angle_get(&triangle.p2, &triangle.p0, &triangle.p1);
2917
2918 if (evas_triangle3_is_line(&triangle))
2919 evas_vec3_set(&big_tangent, 1.0, 0.0, 0.0);
2920
2921 else
2922 tangent_space_weighted_sum(&big_tangent, &little_tangent, &big_angle, little_angle);
2923 }
2924 }
2925 }
2926 }
2927 evas_vec3_set(&normal, normal_data[j], normal_data[j + 1], normal_data[j + 2]);
2928 evas_vec3_orthogonal_projection_on_plain(&big_tangent, &big_tangent, &normal);
2929 evas_vec3_normalize(&big_tangent, &big_tangent);
2930 tmp_tangent[i * 3] = big_tangent.x;
2931 tmp_tangent[i * 3 + 1] = big_tangent.y;
2932 tmp_tangent[i * 3 + 2] = big_tangent.z;
2933 }
2934
2935
2936 memcpy(*tangent, tmp_tangent, (3 * vertex_count) * sizeof(float));
2937 free(tmp_index);
2938 free(tmp_tangent);
2939
2940 return;
2941}