Blender  V2.59
CMP_displace.c
Go to the documentation of this file.
00001 /*
00002  * $Id: CMP_displace.c 36202 2011-04-17 22:47:23Z broken $
00003  *
00004  * ***** BEGIN GPL LICENSE BLOCK *****
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU General Public License
00008  * as published by the Free Software Foundation; either version 2
00009  * of the License, or (at your option) any later version. 
00010  *
00011  * This program is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014  * GNU General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU General Public License
00017  * along with this program; if not, write to the Free Software Foundation,
00018  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00019  *
00020  * The Original Code is Copyright (C) 2006 Blender Foundation.
00021  * All rights reserved.
00022  *
00023  * The Original Code is: all of this file.
00024  *
00025  * Contributor(s): none yet.
00026  *
00027  * ***** END GPL LICENSE BLOCK *****
00028  */
00029 
00035 #include "../CMP_util.h"
00036 
00037 
00038 /* **************** Displace  ******************** */
00039 
00040 static bNodeSocketType cmp_node_displace_in[]= {
00041         {       SOCK_RGBA, 1, "Image",                  0.8f, 0.8f, 0.8f, 1.0f, 0.0f, 1.0f},
00042         {       SOCK_VECTOR, 1, "Vector",                       1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f},
00043         {       SOCK_VALUE, 1, "X Scale",                               0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
00044         {       SOCK_VALUE, 1, "Y Scale",                               0.0f, 0.0f, 0.0f, 0.0f, -1000.0f, 1000.0f},
00045         {       -1, 0, ""       }
00046 };
00047 static bNodeSocketType cmp_node_displace_out[]= {
00048         {       SOCK_RGBA, 0, "Image",                  0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f},
00049         {       -1, 0, ""       }
00050 };
00051 
00052 /* minimum distance (in pixels) a pixel has to be displaced
00053  * in order to take effect */
00054 #define DISPLACE_EPSILON        0.01
00055 
00056 static void do_displace(bNode *node, CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *UNUSED(veccol), CompBuf *xbuf,  CompBuf *ybuf, float *xscale, float *yscale)
00057 {
00058         ImBuf *ibuf;
00059         int x, y;
00060         float p_dx, p_dy;       /* main displacement in pixel space */
00061         float d_dx, d_dy;
00062         float dxt, dyt;
00063         float u, v;
00064         float xs, ys;
00065         float vec[3], vecdx[3], vecdy[3];
00066         float col[3];
00067         
00068         ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
00069         ibuf->rect_float= cbuf->rect;
00070         
00071         for(y=0; y < stackbuf->y; y++) {
00072                 for(x=0; x < stackbuf->x; x++) {
00073                         /* calc pixel coordinates */
00074                         qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof, vec);
00075                         
00076                         if (xbuf)
00077                                 qd_getPixel(xbuf, x-xbuf->xof, y-xbuf->yof, &xs);
00078                         else
00079                                 xs = xscale[0];
00080                         
00081                         if (ybuf)
00082                                 qd_getPixel(ybuf, x-ybuf->xof, y-ybuf->yof, &ys);
00083                         else
00084                                 ys = yscale[0];
00085 
00086                         /* clamp x and y displacement to triple image resolution - 
00087                          * to prevent hangs from huge values mistakenly plugged in eg. z buffers */
00088                         CLAMP(xs, -stackbuf->x*4, stackbuf->x*4);
00089                         CLAMP(ys, -stackbuf->y*4, stackbuf->y*4);
00090                         
00091                         p_dx = vec[0] * xs;
00092                         p_dy = vec[1] * ys;
00093                         
00094                         /* if no displacement, then just copy this pixel */
00095                         if (fabsf(p_dx) < DISPLACE_EPSILON && fabsf(p_dy) < DISPLACE_EPSILON) {
00096                                 qd_getPixel(cbuf, x-cbuf->xof, y-cbuf->yof, col);
00097                                 qd_setPixel(stackbuf, x, y, col);
00098                                 continue;
00099                         }
00100                         
00101                         /* displaced pixel in uv coords, for image sampling */
00102                         u = (x - cbuf->xof - p_dx + 0.5f) / (float)stackbuf->x;
00103                         v = (y - cbuf->yof - p_dy + 0.5f) / (float)stackbuf->y;
00104                         
00105                         
00106                         /* calc derivatives */
00107                         qd_getPixel(vecbuf, x-vecbuf->xof+1, y-vecbuf->yof, vecdx);
00108                         qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof+1, vecdy);
00109                         d_dx = vecdx[0] * xs;
00110                         d_dy = vecdy[0] * ys;
00111 
00112                         /* clamp derivatives to minimum displacement distance in UV space */
00113                         dxt = p_dx - d_dx;
00114                         dyt = p_dy - d_dy;
00115 
00116                         dxt = signf(dxt)*maxf(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x;
00117                         dyt = signf(dyt)*maxf(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y;
00118                         
00119                         ibuf_sample(ibuf, u, v, dxt, dyt, col);
00120                         qd_setPixel(stackbuf, x, y, col);
00121                         
00122                         if(node->exec & NODE_BREAK) break;
00123                 }
00124                 
00125                 if(node->exec & NODE_BREAK) break;
00126         }
00127         IMB_freeImBuf(ibuf);
00128         
00129         
00130 /* simple method for reference, linear interpolation */
00131 /*      
00132         int x, y;
00133         float dx, dy;
00134         float u, v;
00135         float vec[3];
00136         float col[3];
00137         
00138         for(y=0; y < stackbuf->y; y++) {
00139                 for(x=0; x < stackbuf->x; x++) {
00140                         qd_getPixel(vecbuf, x, y, vec);
00141                         
00142                         dx = vec[0] * (xscale[0]);
00143                         dy = vec[1] * (yscale[0]);
00144                         
00145                         u = (x - dx + 0.5f) / (float)stackbuf->x;
00146                         v = (y - dy + 0.5f) / (float)stackbuf->y;
00147                         
00148                         qd_getPixelLerp(cbuf, u*cbuf->x - 0.5f, v*cbuf->y - 0.5f, col);
00149                         qd_setPixel(stackbuf, x, y, col);
00150                 }
00151         }
00152 */
00153 }
00154 
00155 
00156 static void node_composit_exec_displace(void *UNUSED(data), bNode *node, bNodeStack **in, bNodeStack **out)
00157 {
00158         if(out[0]->hasoutput==0)
00159                 return;
00160         
00161         if(in[0]->data && in[1]->data) {
00162                 CompBuf *cbuf= in[0]->data;
00163                 CompBuf *vecbuf= in[1]->data;
00164                 CompBuf *xbuf= in[2]->data;
00165                 CompBuf *ybuf= in[3]->data;
00166                 CompBuf *stackbuf;
00167                 
00168                 cbuf= typecheck_compbuf(cbuf, CB_RGBA);
00169                 vecbuf= typecheck_compbuf(vecbuf, CB_VEC3);
00170                 xbuf= typecheck_compbuf(xbuf, CB_VAL);
00171                 ybuf= typecheck_compbuf(ybuf, CB_VAL);
00172                 
00173                 stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
00174 
00175                 do_displace(node, stackbuf, cbuf, vecbuf, in[1]->vec, xbuf, ybuf, in[2]->vec, in[3]->vec);
00176                 
00177                 out[0]->data= stackbuf;
00178                 
00179                 
00180                 if(cbuf!=in[0]->data)
00181                         free_compbuf(cbuf);
00182                 if(vecbuf!=in[1]->data)
00183                         free_compbuf(vecbuf);
00184         }
00185 }
00186 
00187 void register_node_type_cmp_displace(ListBase *lb)
00188 {
00189         static bNodeType ntype;
00190 
00191         node_type_base(&ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS,
00192                 cmp_node_displace_in, cmp_node_displace_out);
00193         node_type_size(&ntype, 140, 100, 320);
00194         node_type_exec(&ntype, node_composit_exec_displace);
00195 
00196         nodeRegisterType(lb, &ntype);
00197 }
00198 
00199