changeset 9687:86aa08bbc887

image clipping and axes fixes
author Shai Ayal <shaiay@users.sourceforge.net>
date Sat, 03 Oct 2009 10:42:34 -0400
parents 5e433877634f
children 90abfd8a2895
files src/ChangeLog src/gl-render.cc src/graphics.h.in
diffstat 3 files changed, 90 insertions(+), 25 deletions(-) [+]
line wrap: on
line diff
--- a/src/ChangeLog	Fri Oct 02 11:15:02 2009 +0200
+++ b/src/ChangeLog	Sat Oct 03 10:42:34 2009 -0400
@@ -1,3 +1,10 @@
+2009-10-03  Shai Ayal  <shaiay@users.sourceforge.net>
+
+	* graphics.h.in (image::update_xdata): Add a half-pixel to each limit.
+	(image::update_ydata): Ditto.
+	* gl-render.cc (opengl_renderer::draw): Clip image to axis and fix
+	unpack alignment.
+
 2009-10-02  Jaroslav Hajek  <highegg@gmail.com>
 
 	* ov-base-scalar.h (octave_base_scalar::matrix_type): Always
--- a/src/gl-render.cc	Fri Oct 02 11:15:02 2009 +0200
+++ b/src/gl-render.cc	Sat Oct 03 10:42:34 2009 -0400
@@ -2704,8 +2704,53 @@
   const ColumnVector p0 = xform.transform (x(0), y(0), 0);
   const ColumnVector p1 = xform.transform (x(1), y(1), 0);
 
-  glPixelZoom ((p1(0)-p0(0))/(w-1), -(p1(1)-p0(1))/(h-1));
-  glRasterPos3d (x(0)-0.5, y(0)-0.5, 0);
+  // image pixel size in screen pixel units
+  float pix_dx = (p1(0) - p0(0))/(w-1);
+  float pix_dy = (p1(1) - p0(1))/(h-1);
+
+  // image pixel size in normalized units
+  float nor_dx = (x(1) - x(0))/(w-1);
+  float nor_dy = (y(1) - y(0))/(h-1);
+
+  // OpenGL won't draw the image if it's origin is outside the
+  // viewport/clipping plane so we must do the clipping
+  // ourselfes - only draw part of the image
+
+  int j0 = 0, j1 = w;
+  int i0 = 0, i1 = h;
+
+  float im_xmin = x(0) - nor_dx/2;
+  float im_xmax = x(1) + nor_dx/2;
+  float im_ymin = y(0) - nor_dy/2;
+  float im_ymax = y(1) + nor_dy/2;
+  if (props.is_clipping ()) // clip to axes
+    {
+      if (im_xmin < xmin)
+	j0 += (xmin - im_xmin)/nor_dx + 1;
+      if (im_xmax > xmax)
+	j1 -= (im_xmax - xmax)/nor_dx ;
+
+      if (im_ymin < ymin)
+	i0 += (ymin - im_ymin)/nor_dy + 1;
+      if (im_ymax > ymax)
+	i1 -= (im_ymax - ymax)/nor_dy;
+    }
+  else // clip to viewport
+    {
+      GLfloat vp[4];
+      glGetFloatv(GL_VIEWPORT, vp);
+      // FIXME -- actually add the code to do it!
+      
+    }
+
+  if (i0 >= i1 || j0 >= j1) 
+    return;
+
+  glPixelZoom (pix_dx, -pix_dy);
+  glRasterPos3d (im_xmin + nor_dx*j0, im_ymin + nor_dy*i0, 0);
+
+  // by default this is 4
+  glPixelStorei (GL_UNPACK_ALIGNMENT,1);
 
   // Expect RGB data
   if (dv.length () == 3 && dv(2) == 3)
@@ -2714,11 +2759,11 @@
 	{
 	  const NDArray xcdata = cdata.array_value ();
 
-	  OCTAVE_LOCAL_BUFFER (GLfloat, a, (3*w*h));
-
-	  for (int i = 0; i < h; i++)
+	  OCTAVE_LOCAL_BUFFER (GLfloat, a, 3*(j1-j0)*(i1-i0));
+
+	  for (int i = i0; i < i1; i++)
 	    {
-	      for (int j = 0, idx = i*w*3; j < w; j++, idx += 3)
+	      for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
 		{
 		  a[idx]   = xcdata(i,j,0);
 		  a[idx+1] = xcdata(i,j,1);
@@ -2726,18 +2771,18 @@
 		}
 	    }
 
-	  glDrawPixels (w, h, GL_RGB, GL_FLOAT, a);
+	  glDrawPixels (j1-j0, i1-i0, GL_RGB, GL_FLOAT, a);
 
 	}
       else if (cdata.is_uint16_type ())
 	{
-	  const uint8NDArray xcdata = cdata.uint16_array_value ();
-
-	  OCTAVE_LOCAL_BUFFER (octave_uint16, a, (3*w*h));
-
-	  for (int i = 0; i < h; i++)
+	  const uint16NDArray xcdata = cdata.uint16_array_value ();
+
+	  OCTAVE_LOCAL_BUFFER (GLushort, a, 3*(j1-j0)*(i1-i0));
+
+	  for (int i = i0; i < i1; i++)
 	    {
-	      for (int j = 0, idx = i*w*3; j < w; j++, idx += 3)
+	      for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
 		{
 		  a[idx]   = xcdata(i,j,0);
 		  a[idx+1] = xcdata(i,j,1);
@@ -2745,18 +2790,18 @@
 		}
 	    }
 
-	  glDrawPixels (w, h, GL_RGB, GL_UNSIGNED_SHORT, a);
+	  glDrawPixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_SHORT, a);
 
 	}
       else if (cdata.is_uint8_type ())
 	{
 	  const uint8NDArray xcdata = cdata.uint8_array_value ();
 
-	  OCTAVE_LOCAL_BUFFER (octave_uint8, a, (3*w*h));
-
-	  for (int i = 0; i < h; i++)
+	  OCTAVE_LOCAL_BUFFER (GLubyte, a, 3*(j1-j0)*(i1-i0));
+
+	  for (int i = i0; i < i1; i++)
 	    {
-	      for (int j = 0, idx = i*w*3; j < w; j++, idx += 3)
+	      for (int j = j0, idx = (i-i0)*(j1-j0)*3; j < j1; j++, idx += 3)
 		{
 		  a[idx]   = xcdata(i,j,0);
 		  a[idx+1] = xcdata(i,j,1);
@@ -2764,8 +2809,7 @@
 		}
 	    }
 
-	  glDrawPixels (w, h, GL_RGB, GL_UNSIGNED_BYTE, a);
-
+	  glDrawPixels (j1-j0, i1-i0, GL_RGB, GL_UNSIGNED_BYTE, a);
 	}
       else
 	{
--- a/src/graphics.h.in	Fri Oct 02 11:15:02 2009 +0200
+++ b/src/graphics.h.in	Sat Oct 03 10:42:34 2009 -0400
@@ -3175,13 +3175,27 @@
       }
 
   private:
-    // FIXME -- limits should take pixel width into account.
     void update_xdata (void)
-      { set_xlim (xdata.get_limits ()); }
-
-    // FIXME -- idem.
+    { 
+      octave_idx_type iw = (get_cdata ().dims ())(1) - 1;
+      Matrix limits = xdata.get_limits ();
+      float dp = (limits(1) - limits(0))/(2*iw);
+
+      limits(0) = limits(0) - dp;
+      limits(1) = limits(1) + dp;
+      set_xlim (limits); 
+    }
+
     void update_ydata (void)
-      { set_ylim (ydata.get_limits ()); }
+    {
+      octave_idx_type ih = (get_cdata().dims ())(0) - 1;
+      Matrix limits = ydata.get_limits ();
+      float dp = (limits(1) - limits(0))/(2*ih);
+
+      limits(0) = limits(0) - dp;
+      limits(1) = limits(1) + dp;
+      set_ylim (limits); 
+    }
 
     void update_cdata (void)
       {