doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / nodes / intern / CMP_nodes / CMP_displace.c
1 /*
2  * $Id$
3  *
4  * ***** BEGIN GPL LICENSE BLOCK *****
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * as published by the Free Software Foundation; either version 2
9  * of the License, or (at your option) any later version. 
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19  *
20  * The Original Code is Copyright (C) 2006 Blender Foundation.
21  * All rights reserved.
22  *
23  * The Original Code is: all of this file.
24  *
25  * Contributor(s): none yet.
26  *
27  * ***** END GPL LICENSE BLOCK *****
28  */
29
30 #include "../CMP_util.h"
31
32
33 /* **************** Displace  ******************** */
34
35 static bNodeSocketType cmp_node_displace_in[]= {
36         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
37         {       SOCK_VECTOR, 1, "Vector",                       1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
38         {       SOCK_VALUE, 1, "X Scale",                               0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
39         {       SOCK_VALUE, 1, "Y Scale",                               0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
40         {       -1, 0, ""       }
41 };
42 static bNodeSocketType cmp_node_displace_out[]= {
43         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
44         {       -1, 0, ""       }
45 };
46
47 /* minimum distance (in pixels) a pixel has to be displaced
48  * in order to take effect */
49 #define DISPLACE_EPSILON        0.01
50
51 static void do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *UNUSED(veccol), CompBuf *xbuf,  CompBuf *ybuf, float *xscale, float *yscale)
52 {
53         ImBuf *ibuf;
54         int x, y;
55         float p_dx, p_dy;       /* main displacement in pixel space */
56         float d_dx, d_dy;
57         float dxt, dyt;
58         float u, v;
59         float xs, ys;
60         float vec[3], vecdx[3], vecdy[3];
61         float col[3];
62         
63         ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
64         ibuf->rect_float= cbuf->rect;
65         
66         for(y=0; y < stackbuf->y; y++) {
67                 for(x=0; x < stackbuf->x; x++) {
68                         /* calc pixel coordinates */
69                         qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof, vec);
70                         
71                         if (xbuf)
72                                 qd_getPixel(xbuf, x-xbuf->xof, y-xbuf->yof, &xs);
73                         else
74                                 xs = xscale[0];
75                         
76                         if (ybuf)
77                                 qd_getPixel(ybuf, x-ybuf->xof, y-ybuf->yof, &ys);
78                         else
79                                 ys = yscale[0];
80
81                         
82                         p_dx = vec[0] * xs;
83                         p_dy = vec[1] * ys;
84                         
85                         /* if no displacement, then just copy this pixel */
86                         if (fabsf(p_dx) < DISPLACE_EPSILON && fabsf(p_dy) < DISPLACE_EPSILON) {
87                                 qd_getPixel(cbuf, x-cbuf->xof, y-cbuf->yof, col);
88                                 qd_setPixel(stackbuf, x, y, col);
89                                 continue;
90                         }
91                         
92                         /* displaced pixel in uv coords, for image sampling */
93                         u = (x - cbuf->xof - p_dx + 0.5f) / (float)stackbuf->x;
94                         v = (y - cbuf->yof - p_dy + 0.5f) / (float)stackbuf->y;
95                         
96                         
97                         /* calc derivatives */
98                         qd_getPixel(vecbuf, x-vecbuf->xof+1, y-vecbuf->yof, vecdx);
99                         qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof+1, vecdy);
100                         d_dx = vecdx[0] * xs;
101                         d_dy = vecdy[0] * ys;
102
103                         /* clamp derivatives to minimum displacement distance in UV space */
104                         dxt = p_dx - d_dx;
105                         dyt = p_dy - d_dy;
106
107                         dxt = signf(dxt)*maxf(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x;
108                         dyt = signf(dyt)*maxf(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y;
109                         
110                         ibuf_sample(ibuf, u, v, dxt, dyt, col);
111                         qd_setPixel(stackbuf, x, y, col);
112                 }
113         }
114         IMB_freeImBuf(ibuf);
115         
116         
117 /* simple method for reference, linear interpolation */
118 /*      
119         int x, y;
120         float dx, dy;
121         float u, v;
122         float vec[3];
123         float col[3];
124         
125         for(y=0; y < stackbuf->y; y++) {
126                 for(x=0; x < stackbuf->x; x++) {
127                         qd_getPixel(vecbuf, x, y, vec);
128                         
129                         dx = vec[0] * (xscale[0]);
130                         dy = vec[1] * (yscale[0]);
131                         
132                         u = (x - dx + 0.5f) / (float)stackbuf->x;
133                         v = (y - dy + 0.5f) / (float)stackbuf->y;
134                         
135                         qd_getPixelLerp(cbuf, u*cbuf->x - 0.5f, v*cbuf->y - 0.5f, col);
136                         qd_setPixel(stackbuf, x, y, col);
137                 }
138         }
139 */
140 }
141
142
143 static void node_composit_exec_displace(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
144 {
145         if(out[0]->hasoutput==0)
146                 return;
147         
148         if(in[0]->data && in[1]->data) {
149                 CompBuf *cbuf= in[0]->data;
150                 CompBuf *vecbuf= in[1]->data;
151                 CompBuf *xbuf= in[2]->data;
152                 CompBuf *ybuf= in[3]->data;
153                 CompBuf *stackbuf;
154                 
155                 cbuf= typecheck_compbuf(cbuf, CB_RGBA);
156                 vecbuf= typecheck_compbuf(vecbuf, CB_VEC3);
157                 xbuf= typecheck_compbuf(xbuf, CB_VAL);
158                 ybuf= typecheck_compbuf(ybuf, CB_VAL);
159                 
160                 stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
161
162                 do_displace(stackbuf, cbuf, vecbuf, in[1]->vec, xbuf, ybuf, in[2]->vec, in[3]->vec);
163                 
164                 out[0]->data= stackbuf;
165                 
166                 
167                 if(cbuf!=in[0]->data)
168                         free_compbuf(cbuf);
169                 if(vecbuf!=in[1]->data)
170                         free_compbuf(vecbuf);
171         }
172 }
173
174 void register_node_type_cmp_displace(ListBase *lb)
175 {
176         static bNodeType ntype;
177
178         node_type_base(&ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS,
179                 cmp_node_displace_in, cmp_node_displace_out);
180         node_type_size(&ntype, 140, 100, 320);
181         node_type_exec(&ntype, node_composit_exec_displace);
182
183         nodeRegisterType(lb, &ntype);
184 }
185
186