|
Blender
V2.59
|
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