doxygen: prevent GPL license block from being parsed as doxygen comment.
[blender.git] / source / blender / nodes / intern / CMP_nodes / CMP_displace.c
index 760d1107d4c15574091895135fd994fb1379e8e9..49b65ef05981e8c49c4e5bb81f30f4299ad89907 100644 (file)
@@ -1,4 +1,4 @@
-/**
+/*
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
@@ -15,7 +15,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2006 Blender Foundation.
  * All rights reserved.
  *
  * The Original Code is Copyright (C) 2006 Blender Foundation.
  * All rights reserved.
@@ -44,81 +44,103 @@ static bNodeSocketType cmp_node_displace_out[]= {
        {       -1, 0, ""       }
 };
 
        {       -1, 0, ""       }
 };
 
-static void do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *veccol, float *xscale, float *yscale)
+/* minimum distance (in pixels) a pixel has to be displaced
+ * in order to take effect */
+#define DISPLACE_EPSILON       0.01
+
+static void do_displace(CompBuf *stackbuf, CompBuf *cbuf, CompBuf *vecbuf, float *UNUSED(veccol), CompBuf *xbuf,  CompBuf *ybuf, float *xscale, float *yscale)
 {
        ImBuf *ibuf;
 {
        ImBuf *ibuf;
-       int x, y, sx, sy;
-       float dx=0.0, dy=0.0;
-       float dspx, dspy;
-       float uv[2];
-
-       float *out= stackbuf->rect, *vec=vecbuf->rect, *in= cbuf->rect;
-       float *vp, *vpnext, *vpprev;
+       int x, y;
+       float p_dx, p_dy;       /* main displacement in pixel space */
+       float d_dx, d_dy;
+       float dxt, dyt;
+       float u, v;
+       float xs, ys;
+       float vec[3], vecdx[3], vecdy[3];
+       float col[3];
        
        
-       int row = 3*vecbuf->x;
-       
-       /* ibuf needed for sampling */
-       ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0, 0);
+       ibuf= IMB_allocImBuf(cbuf->x, cbuf->y, 32, 0);
        ibuf->rect_float= cbuf->rect;
        
        ibuf->rect_float= cbuf->rect;
        
-       vec = vecbuf->rect;
-       
-       sx= stackbuf->x;
-       sy= stackbuf->y;
-       
-       for(y=0; y<sy; y++) {
-               for(x= 0; x< sx; x++, out+=4, in+=4, vec+=3) {
+       for(y=0; y < stackbuf->y; y++) {
+               for(x=0; x < stackbuf->x; x++) {
+                       /* calc pixel coordinates */
+                       qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof, vec);
                        
                        
-                       /* the x-xrad stuff is a bit weird, but i seem to need it otherwise 
-                        * my returned pixels are offset weirdly */
-                       vp = compbuf_get_pixel(vecbuf, veccol, x-vecbuf->xrad, y-vecbuf->yrad, vecbuf->xrad, vecbuf->yrad);
+                       if (xbuf)
+                               qd_getPixel(xbuf, x-xbuf->xof, y-xbuf->yof, &xs);
+                       else
+                               xs = xscale[0];
                        
                        
-                       /* find the new displaced co-ords, also correcting for translate offset */
-                       dspx = x - (*xscale * vp[0]);
-                       dspy = y - (*yscale * vp[1]);
+                       if (ybuf)
+                               qd_getPixel(ybuf, x-ybuf->xof, y-ybuf->yof, &ys);
+                       else
+                               ys = yscale[0];
 
 
-                       /* convert image space to 0.0-1.0 UV space for sampling, correcting for translate offset */
-                       uv[0] = dspx / (float)sx;
-                       uv[1] = dspy / (float)sy;
                        
                        
-                       if(x>0 && x< vecbuf->x-1 && y>0 && y< vecbuf->y-1)  {
-                               vpnext = vp+row;
-                               vpprev = vp-row;
+                       p_dx = vec[0] * xs;
+                       p_dy = vec[1] * ys;
                        
                        
-                               /* adaptive sampling, X channel */
-                               dx= 0.5f*(fabs(vp[0]-vp[-3]) + fabs(vp[0]-vp[3]));
-                               
-                               dx+= 0.25f*(fabs(vp[0]-vpprev[-3]) + fabs(vp[0]-vpnext[-3]));
-                               dx+= 0.25f*(fabs(vp[0]-vpprev[+3]) + fabs(vp[0]-vpnext[+3]));
-                               
-                               /* adaptive sampling, Y channel */
-                               dy= 0.5f*(fabs(vp[1]-vp[-row+1]) + fabs(vp[1]-vp[row+1]));
-                                                
-                               dy+= 0.25f*(fabs(vp[1]-vpprev[+1-3]) + fabs(vp[1]-vpnext[+1-3]));
-                               dy+= 0.25f*(fabs(vp[1]-vpprev[+1+3]) + fabs(vp[1]-vpnext[+1+3]));
-                               
-                               /* scaled down to prevent blurriness */
-                               /* 8: magic number, provides a good level of sharpness without getting too aliased */
-                               dx /= 8;
-                               dy /= 8;
+                       /* if no displacement, then just copy this pixel */
+                       if (fabsf(p_dx) < DISPLACE_EPSILON && fabsf(p_dy) < DISPLACE_EPSILON) {
+                               qd_getPixel(cbuf, x-cbuf->xof, y-cbuf->yof, col);
+                               qd_setPixel(stackbuf, x, y, col);
+                               continue;
                        }
                        }
-
-                       /* should use mipmap */
-                       if(dx > 0.006f) dx= 0.006f;
-                       if(dy > 0.006f) dy= 0.006f;
-                       if ((vp[0]> 0.0) && (dx < 0.004)) dx = 0.004;
-                       if ((vp[1]> 0.0) && (dy < 0.004)) dy = 0.004;
                        
                        
+                       /* displaced pixel in uv coords, for image sampling */
+                       u = (x - cbuf->xof - p_dx + 0.5f) / (float)stackbuf->x;
+                       v = (y - cbuf->yof - p_dy + 0.5f) / (float)stackbuf->y;
+                       
+                       
+                       /* calc derivatives */
+                       qd_getPixel(vecbuf, x-vecbuf->xof+1, y-vecbuf->yof, vecdx);
+                       qd_getPixel(vecbuf, x-vecbuf->xof, y-vecbuf->yof+1, vecdy);
+                       d_dx = vecdx[0] * xs;
+                       d_dy = vecdy[0] * ys;
+
+                       /* clamp derivatives to minimum displacement distance in UV space */
+                       dxt = p_dx - d_dx;
+                       dyt = p_dy - d_dy;
 
 
-                       ibuf_sample(ibuf, uv[0], uv[1], dx, dy, out);
+                       dxt = signf(dxt)*maxf(fabsf(dxt), DISPLACE_EPSILON)/(float)stackbuf->x;
+                       dyt = signf(dyt)*maxf(fabsf(dyt), DISPLACE_EPSILON)/(float)stackbuf->y;
+                       
+                       ibuf_sample(ibuf, u, v, dxt, dyt, col);
+                       qd_setPixel(stackbuf, x, y, col);
                }
        }
                }
        }
-
-       IMB_freeImBuf(ibuf);    
+       IMB_freeImBuf(ibuf);
+       
+       
+/* simple method for reference, linear interpolation */
+/*     
+       int x, y;
+       float dx, dy;
+       float u, v;
+       float vec[3];
+       float col[3];
+       
+       for(y=0; y < stackbuf->y; y++) {
+               for(x=0; x < stackbuf->x; x++) {
+                       qd_getPixel(vecbuf, x, y, vec);
+                       
+                       dx = vec[0] * (xscale[0]);
+                       dy = vec[1] * (yscale[0]);
+                       
+                       u = (x - dx + 0.5f) / (float)stackbuf->x;
+                       v = (y - dy + 0.5f) / (float)stackbuf->y;
+                       
+                       qd_getPixelLerp(cbuf, u*cbuf->x - 0.5f, v*cbuf->y - 0.5f, col);
+                       qd_setPixel(stackbuf, x, y, col);
+               }
+       }
+*/
 }
 
 
 }
 
 
-static void node_composit_exec_displace(void *data, bNode *node, bNodeStack **in, bNodeStack **out)
+static void node_composit_exec_displace(void *UNUSED(data), bNode *UNUSED(node), bNodeStack **in, bNodeStack **out)
 {
        if(out[0]->hasoutput==0)
                return;
 {
        if(out[0]->hasoutput==0)
                return;
@@ -126,13 +148,18 @@ static void node_composit_exec_displace(void *data, bNode *node, bNodeStack **in
        if(in[0]->data && in[1]->data) {
                CompBuf *cbuf= in[0]->data;
                CompBuf *vecbuf= in[1]->data;
        if(in[0]->data && in[1]->data) {
                CompBuf *cbuf= in[0]->data;
                CompBuf *vecbuf= in[1]->data;
+               CompBuf *xbuf= in[2]->data;
+               CompBuf *ybuf= in[3]->data;
                CompBuf *stackbuf;
                
                cbuf= typecheck_compbuf(cbuf, CB_RGBA);
                vecbuf= typecheck_compbuf(vecbuf, CB_VEC3);
                CompBuf *stackbuf;
                
                cbuf= typecheck_compbuf(cbuf, CB_RGBA);
                vecbuf= typecheck_compbuf(vecbuf, CB_VEC3);
+               xbuf= typecheck_compbuf(xbuf, CB_VAL);
+               ybuf= typecheck_compbuf(ybuf, CB_VAL);
+               
                stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
 
                stackbuf= alloc_compbuf(cbuf->x, cbuf->y, CB_RGBA, 1); /* allocs */
 
-               do_displace(stackbuf, cbuf, vecbuf, in[1]->vec, in[2]->vec, in[3]->vec);
+               do_displace(stackbuf, cbuf, vecbuf, in[1]->vec, xbuf, ybuf, in[2]->vec, in[3]->vec);
                
                out[0]->data= stackbuf;
                
                
                out[0]->data= stackbuf;
                
@@ -144,16 +171,16 @@ static void node_composit_exec_displace(void *data, bNode *node, bNodeStack **in
        }
 }
 
        }
 }
 
-bNodeType cmp_node_displace= {
-       /* type code   */       CMP_NODE_DISPLACE,
-       /* name        */       "Displace",
-       /* width+range */       140, 100, 320,
-       /* class+opts  */       NODE_CLASS_DISTORT, NODE_OPTIONS,
-       /* input sock  */       cmp_node_displace_in,
-       /* output sock */       cmp_node_displace_out,
-       /* storage     */       "",
-       /* execfunc    */       node_composit_exec_displace, 
-       /* butfunc     */       NULL,
-       /* initfunc    */       NULL
-};
+void register_node_type_cmp_displace(ListBase *lb)
+{
+       static bNodeType ntype;
+
+       node_type_base(&ntype, CMP_NODE_DISPLACE, "Displace", NODE_CLASS_DISTORT, NODE_OPTIONS,
+               cmp_node_displace_in, cmp_node_displace_out);
+       node_type_size(&ntype, 140, 100, 320);
+       node_type_exec(&ntype, node_composit_exec_displace);
+
+       nodeRegisterType(lb, &ntype);
+}
+