Code

Super duper mega (fun!) commit: replaced encoding=utf-8 with fileencoding=utf-8 in...
[inkscape.git] / src / display / nr-3dutils.cpp
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 "display/nr-3dutils.h"
16 #include <cmath>
18 namespace NR {
20 #define BEGIN 0 // TOP or LEFT
21 #define MIDDLE 1
22 #define END 2 // BOTTOM or RIGHT
24 #define START(v) ((v)==BEGIN? 1 : 0)
25 #define FINISH(v) ((v)==END? 1 : 2)
27 signed char K_X[3][3][3][3] = {
28     //K_X[TOP]
29     {
30         //K_X[TOP][LEFT]
31         {
32             { 0,  0,  0},
33             { 0, -2,  2},
34             { 0, -1,  1}
35         },
36         {
37             { 0,  0,  0},
38             {-2,  0,  2},
39             {-1,  0,  1}
40         },
41         {
42             { 0,  0,  0},
43             {-2,  2,  0},
44             {-1,  1,  0}
45         }
46     },
47     //K_X[MIDDLE]
48     {
49         //K_X[MIDDLE][LEFT]
50         {
51             { 0, -1,  1},
52             { 0, -2,  2},
53             { 0, -1,  1}
54         },
55         {
56             {-1,  0,  1},
57             {-2,  0,  2},
58             {-1,  0,  1}
59         },
60         {
61             {-1,  1,  0},
62             {-2,  2,  0},
63             {-1,  1,  0}
64         }
65     },
66     //K_X[BOTTOM]
67     {
68         //K_X[BOTTOM][LEFT]
69         {
70             { 0, -1,  1},
71             { 0, -2,  2},
72             { 0,  0,  0}
73         },
74         {
75             {-1,  0,  1},
76             {-2,  0,  2},
77             { 0,  0,  0}
78         },
79         {
80             {-1,  1,  0},
81             {-2,  2,  0},
82             { 0,  0,  0}
83         }
84     }
85 };
87 //K_Y is obtained by transposing K_X globally and each of its components
89 gdouble FACTOR_X[3][3] = {
90     {2./3, 1./3, 2./3},
91     {1./2, 1./4, 1./2},
92     {2./3, 1./3, 2./3}
93 };
95 //FACTOR_Y is obtained by transposing FACTOR_X
97 inline
98 int get_carac(int i, int len, int delta) {
99     if (i < delta)
100         return BEGIN;
101     else if (i > len - 1 - delta)
102         return END;
103     else
104         return MIDDLE;
107 //assumes in is RGBA
108 //should be made more resistant
109 void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j, int dx, int dy) {
110     int w = in->area.x1 - in->area.x0;
111     int h = in->area.y1 - in->area.y0;
112     int k, l, alpha_idx, alpha_idx_y;
113     int x_carac, y_carac;
114     gdouble alpha;
115     gdouble accu_x;
116     gdouble accu_y;
117     unsigned char *data = NR_PIXBLOCK_PX (in);
118     g_assert(NR_PIXBLOCK_BPP(in) == 4);
119     x_carac = get_carac(j, w, dx); //LEFT, MIDDLE or RIGHT
120     y_carac = get_carac(i, h, dy); //TOP, MIDDLE or BOTTOM
121     alpha_idx = 4*(i*w + j);
122     accu_x = 0;
123     accu_y = 0;
124     for (k = START(y_carac); k <= FINISH(y_carac); k++) {
125         alpha_idx_y = alpha_idx + 4*(k-1)*dy*w;
126         for (l = START(x_carac); l <= FINISH(x_carac); l++) {
127             alpha = (data + alpha_idx_y + 4*dx*(l-1))[3];
128             accu_x += K_X[y_carac][x_carac][k][l] * alpha;
129             accu_y += K_X[x_carac][y_carac][l][k] * alpha;
130         }
131     }
132     ss /= 255.0; // Correction for scale of pixel values
133     N[X_3D] = -ss * FACTOR_X[y_carac][x_carac] * accu_x / dx;
134     N[Y_3D] = -ss * FACTOR_X[x_carac][y_carac] * accu_y / dy;
135     N[Z_3D] = 1.0;
136     normalize_vector(N);
137     //std::cout << "(" << N[X_3D] << ", " << N[Y_3D] << ", " << N[Z_3D] << ")" << std::endl;
140 void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Matrix const &trans) {
141     Point p = Point(x, y);
142     p *= trans;
143     x = p[Geom::X];
144     y = p[Geom::Y];
145     z *= trans[0];
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]);
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     }
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];
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);
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:fileencoding=utf-8:textwidth=99 :