Blender V2.61 - r43446
|
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 }