Blender V2.61 - r43446

node_composite_displace.c

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