1 /*
2 * 3D utils.
3 *
4 * Authors:
5 * Jean-Rene Reinhard <jr@komite.net>
6 *
7 * Copyright (C) 2007 authors
8 *
9 * Released under GNU GPL, read the file 'COPYING' for more information
10 */
12 #include <glib/gmessages.h>
14 #include "libnr/nr-pixblock.h"
15 #include "libnr/nr-matrix.h"
16 #include "display/nr-3dutils.h"
17 #include <cmath>
19 namespace NR {
21 #define BEGIN 0 // TOP or LEFT
22 #define MIDDLE 1
23 #define END 2 // BOTTOM or RIGHT
25 #define START(v) ((v)==BEGIN? 1 : 0)
26 #define FINISH(v) ((v)==END? 1 : 2)
28 signed char K_X[3][3][3][3] = {
29 //K_X[TOP]
30 {
31 //K_X[TOP][LEFT]
32 {
33 { 0, 0, 0},
34 { 0, -2, 2},
35 { 0, -1, 1}
36 },
37 {
38 { 0, 0, 0},
39 {-2, 0, 2},
40 {-1, 0, 1}
41 },
42 {
43 { 0, 0, 0},
44 {-2, 2, 0},
45 {-1, 1, 0}
46 }
47 },
48 //K_X[MIDDLE]
49 {
50 //K_X[MIDDLE][LEFT]
51 {
52 { 0, -1, 1},
53 { 0, -2, 2},
54 { 0, -1, 1}
55 },
56 {
57 {-1, 0, 1},
58 {-2, 0, 2},
59 {-1, 0, 1}
60 },
61 {
62 {-1, 1, 0},
63 {-2, 2, 0},
64 {-1, 1, 0}
65 }
66 },
67 //K_X[BOTTOM]
68 {
69 //K_X[BOTTOM][LEFT]
70 {
71 { 0, -1, 1},
72 { 0, -2, 2},
73 { 0, 0, 0}
74 },
75 {
76 {-1, 0, 1},
77 {-2, 0, 2},
78 { 0, 0, 0}
79 },
80 {
81 {-1, 1, 0},
82 {-2, 2, 0},
83 { 0, 0, 0}
84 }
85 }
86 };
88 //K_Y is obtained by transposing K_X globally and each of its components
90 gdouble FACTOR_X[3][3] = {
91 {2./3, 1./3, 2./3},
92 {1./2, 1./4, 1./2},
93 {2./3, 1./3, 2./3}
94 };
96 //FACTOR_Y is obtained by transposing FACTOR_X
98 inline
99 int get_carac(int i, int len, int delta) {
100 if (i < delta)
101 return BEGIN;
102 else if (i > len - 1 - delta)
103 return END;
104 else
105 return MIDDLE;
106 }
108 //assumes in is RGBA
109 //should be made more resistant
110 void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j, int dx, int dy) {
111 int w = in->area.x1 - in->area.x0;
112 int h = in->area.y1 - in->area.y0;
113 int k, l, alpha_idx, alpha_idx_y;
114 int x_carac, y_carac;
115 gdouble alpha;
116 gdouble accu_x;
117 gdouble accu_y;
118 unsigned char *data = NR_PIXBLOCK_PX (in);
119 g_assert(NR_PIXBLOCK_BPP(in) == 4);
120 x_carac = get_carac(j, w, dx); //LEFT, MIDDLE or RIGHT
121 y_carac = get_carac(i, h, dy); //TOP, MIDDLE or BOTTOM
122 alpha_idx = 4*(i*w + j);
123 accu_x = 0;
124 accu_y = 0;
125 for (k = START(y_carac); k <= FINISH(y_carac); k++) {
126 alpha_idx_y = alpha_idx + 4*(k-1)*dy*w;
127 for (l = START(x_carac); l <= FINISH(x_carac); l++) {
128 alpha = (data + alpha_idx_y + 4*dx*(l-1))[3];
129 accu_x += K_X[y_carac][x_carac][k][l] * alpha / 255;
130 accu_y += K_X[x_carac][y_carac][l][k] * alpha / 255;
131 }
132 }
133 N[X_3D] = -1 * ss * FACTOR_X[y_carac][x_carac] * accu_x / dx;
134 N[Y_3D] = -1 * ss * FACTOR_X[x_carac][y_carac] * accu_y / dy;
135 N[Z_3D] = 1;
136 normalize_vector(N);
137 //std::cout << "(" << N[X_3D] << ", " << N[Y_3D] << ", " << N[Z_3D] << ")" << std::endl;
138 }
140 void convert_coord(gdouble &x, gdouble &y, gdouble &z, Matrix const &trans) {
141 Point p = Point(x, y);
142 p *= trans;
143 x = p[X];
144 y = p[Y];
145 z *= trans[0];
146 }
148 gdouble norm(const Fvector &v) {
149 return sqrt(v[X_3D]*v[X_3D] + v[Y_3D]*v[Y_3D] + v[Z_3D]*v[Z_3D]);
150 }
152 void normalize_vector(Fvector &v) {
153 gdouble nv = norm(v);
154 //TODO test nv == 0
155 for (int j = 0; j < 3; j++) {
156 v[j] /= nv;
157 }
158 }
160 gdouble scalar_product(const Fvector &a, const Fvector &b) {
161 return a[X_3D] * b[X_3D] +
162 a[Y_3D] * b[Y_3D] +
163 a[Z_3D] * b[Z_3D];
164 }
166 void normalized_sum(Fvector &r, const Fvector &a, const Fvector &b) {
167 r[X_3D] = a[X_3D] + b[X_3D];
168 r[Y_3D] = a[Y_3D] + b[Y_3D];
169 r[Z_3D] = a[Z_3D] + b[Z_3D];
170 normalize_vector(r);
171 }
173 }/* namespace NR */
175 /*
176 Local Variables:
177 mode:c++
178 c-file-style:"stroustrup"
179 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
180 indent-tabs-mode:nil
181 fill-column:99
182 End:
183 */
184 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :