loan@Neon.Stanford.EDU (James P. Loan) (02/09/91)
I'm trying to draw several copies of the same polygon and I'm having a hard time getting them to look EXACTLY alike. I realize that there is round-off error when translating within a window, but the manual presents a way to fix that. I thought the purpose of the +/-0.5 adjustment in an ortho2() call was to "move" the coordinate system so that integer vertices would fall exactly in the center of pixels. Well, I wrote a test program which seems to prove exactly the opposite. When I add in the +/-0.5 adjustment, there is [round-off] error which makes one copy of a trapezoid smaller than the other (sometimes). When I take out the adjustment, there is no difference between the polygons. Since the error involves the top (flat) edge of the trapezoid, it must mean that the top two vertices are falling on pixel edges. By the way, the same problem arises if I draw screen-aligned rectangles instead of trapezoids, so the problem is with VERTICES falling on pixel edges, not points on the lines connecting the vertices. Can anyone explain to me what is going on? Sample program follows. thanks for any help with this trivial but annoying problem, pete loan loan@neon.stanford.edu /* Test file for problem with translating point-sampled polygons. * To see the problem: * (1) Compile this file: cc -o test test.c -lgl_s * (2) Get /usr/demos/bin/snoop running and turn Cmode on. * (3) Run the test program: test * (4) Use snoop to check out the HEIGHT of the two trapezoids * (5) Resize the test window so it is at least 700 pixels HIGH * (6) Use snoop again to check the HEIGHT of the trapezoids * (7) Edit this file so that the other ORTHO2 command is used. * (8) Repeat steps (1) - (6). */ #include <gl/gl.h> #include <gl/device.h> main() { short val; long id, xs, ys; prefposition(100,300,100,200); id = winopen(""); winconstraints(); qdevice(ESCKEY); qdevice(REDRAW); qenter(REDRAW,id); while (1) { switch (qread(&val)) { case REDRAW: getsize(&xs,&ys); viewport(0,(Screencoord)xs-1,0,(Screencoord)ys-1); ortho2(-0.5,(Coord)xs+0.5,-0.5,(Coord)ys+0.5); /* ortho2(0.0,(Coord)xs+1,0.0,(Coord)ys+1); */ color(0); clear(); color(5); pushmatrix(); translate(0.0,(Coord)ys-25.0,0.0); trapezoid(); translate(0.0,-20.0,0.0); trapezoid(); popmatrix(); break; case ESCKEY: exit(0); } } } int pts[][2] = { {40,20}, {10,20}, {13,17}, {37,17} }; trapezoid() { bgnpolygon(); v2i(pts[0]); v2i(pts[1]); v2i(pts[2]); v2i(pts[3]); endpolygon(); }
andru@electron.lcs.mit.edu (imagician) (02/09/91)
In article <1991Feb8.200816.20381@Neon.Stanford.EDU> loan@Neon.Stanford.EDU (James P. Loan) writes: > >I'm trying to draw several copies of the same polygon and I'm having >a hard time getting them to look EXACTLY alike. I realize that there >is round-off error when translating within a window, but the manual >presents a way to fix that. I thought the purpose of the +/-0.5 >adjustment in an ortho2() call was to "move" the coordinate system >so that integer vertices would fall exactly in the center of pixels. [...] >not points on the lines connecting the vertices. > viewport(0,(Screencoord)xs-1,0,(Screencoord)ys-1); > ortho2(-0.5,(Coord)xs+0.5,-0.5,(Coord)ys+0.5); >/* ortho2(0.0,(Coord)xs+1,0.0,(Coord)ys+1); */ Your ortho calls are wrong. The viewport is xs pixels wide, but you are mapping a coordinate system which is (xs+1) wide onto it. What you want is ortho2(-0.5, (Coord)xs-0.5, -0.5, (Coord)ys-0.5); Any apparent discrepancy is because viewport() takes pixel indices as arguments, whereas ortho() calls take coordinates as arguments. Andrew
bennett@sgi.com (Jim Bennett) (02/09/91)
In article <1991Feb8.200816.20381@Neon.Stanford.EDU> loan@Neon.Stanford.EDU (James P. Loan) writes: > >I'm trying to draw several copies of the same polygon and I'm having >a hard time getting them to look EXACTLY alike. I realize that there >is round-off error when translating within a window, but the manual >presents a way to fix that. I thought the purpose of the +/-0.5 >adjustment in an ortho2() call was to "move" the coordinate system >so that integer vertices would fall exactly in the center of pixels. >Well, I wrote a test program which seems to prove exactly the opposite. >When I add in the +/-0.5 adjustment, there is [round-off] error which >makes one copy of a trapezoid smaller than the other (sometimes). When >I take out the adjustment, there is no difference between the polygons. >Since the error involves the top (flat) edge of the trapezoid, it must >mean that the top two vertices are falling on pixel edges. By the way, >the same problem arises if I draw screen-aligned rectangles instead >of trapezoids, so the problem is with VERTICES falling on pixel edges, >not points on the lines connecting the vertices. > >Can anyone explain to me what is going on? This discussion only applies to applications who want to use pixel coordinates. The .5 offsets do put integer coordinates at pixel centers. So when you draw a line with integer vertices, it interpolates between the pixel centers, just the way you expect. If you draw a polygon with integer vertices, the polygon you get is the interior of the region formed by connecting the pixel centers. For any pixel, if its center is inside this region, then the pixel belongs to the polygon, otherwise it doesn't. When the edge of a polygon passes exactly through a pixel center, then the pixel is included in the polygon if it is on a left or lower edge, and excluded if it is on a right or upper edge. On a VGX or a GT, the computations are done correctly, and you should get the same polygon regardless of where it is drawn within the window or on the screen. On a PI, the round off error causes different effects in different quadrants of the viewport. To fix this problem, you can use an offset of 0.49 instead of 0.5, and then the PI will behave more nicely. However, there will still be (rare) cases where a polygon will light up different pixels, depending on its location. Jim Bennett (bennett@esd.sgi.com)
garyt@westcoast.esd.sgi.com (Gary Tarolli) (02/12/91)
In article <1991Feb8.200816.20381@Neon.Stanford.EDU>, loan@Neon.Stanford.EDU (James P. Loan) writes: > > I'm trying to draw several copies of the same polygon and I'm having > a hard time getting them to look EXACTLY alike. I realize that there > is round-off error when translating within a window, but the manual > presents a way to fix that. I thought the purpose of the +/-0.5 > adjustment in an ortho2() call was to "move" the coordinate system > so that integer vertices would fall exactly in the center of pixels. > Well, I wrote a test program which seems to prove exactly the opposite. > When I add in the +/-0.5 adjustment, there is [round-off] error which > makes one copy of a trapezoid smaller than the other (sometimes). When > I take out the adjustment, there is no difference between the polygons. > Since the error involves the top (flat) edge of the trapezoid, it must > mean that the top two vertices are falling on pixel edges. By the way, > the same problem arises if I draw screen-aligned rectangles instead > of trapezoids, so the problem is with VERTICES falling on pixel edges, > not points on the lines connecting the vertices. > > Can anyone explain to me what is going on? > When you are drawing old style polygons, you want your polygon vertices to land exactly on pixel centers. But when you are drawing point-sampled polygons you want the opposite - you should place your vertices exactly on the pixel borders. This is because the decision to fill a pixel or not is based on whether the pixel center is in/outside of the polygon. If the polygon edge goes right thru the center of a pixel, then you are susceptable to round off error. If you move your vertices to pixel borders (1.5, 2.5, etc) then it takes a big roundoff error to make things fail ( magnitude of .5). Warning - if you attempt to do this by introducing a translate matrix, beware if you are ddrawing lines - it may have an undesired effect on lines. Andrew Meyers once went thru all this and came up with a scheme for drawing exact polygons on all our machines for doing 2-D User Interface code. Any comments Andrew? -------------------- Gary Tarolli
andru@electron.lcs.mit.edu (Andrew Myers) (02/12/91)
In article <84845@sgi.sgi.com> garyt@westcoast.esd.sgi.com (Gary Tarolli) writes: >When you are drawing old style polygons, you want your polygon vertices to >land exactly on pixel centers. But when you are drawing point-sampled >polygons you want the opposite - you should place your vertices exactly >on the pixel borders. This is because the decision to fill a pixel or not >is based on whether the pixel center is in/outside of the polygon. If >the polygon edge goes right thru the center of a pixel, then you are >susceptable to round off error. If you move your vertices to pixel >borders (1.5, 2.5, etc) then it takes a big roundoff error to make >things fail ( magnitude of .5). This is of course correct. Drawing lines & points is sort of antithetical to drawing new-style point-sampled polygons. You can think of lines, points and old-style polygons as new-style polygons which have been bloated by 0.5 pixels. This can cause problems in some programs. In the case of the program which was presented, I believe the problem was simply a bad ortho2() call, as I stated in an earlier article. If you want to draw true point-sampled polygons, you should note that it is only supported on the PI and the VGX. The GT supports new-style polygons but does not do point-sampling. You should set your ortho2 call to either (0,xs,0,ys) or (-0.5, xs-0.5, -0.5, ys-0.5) depending on whether you are in new-style polygon mode or old-style, respectively. Old-style is the default mode, last time I checked. If you want to use new-style polygons and have your lines work well, then you should ensure that the line goes down the center of the pixel. This can be done by either using coordinates with a .5 adjustment, or by a translate(0.5,0.5,0.0) call followed by an opposing translate() when you are finished drawing lines and points. I recommend using new-style polygons. And if you are doing user interface work, use the sbox() calls whenever possible. Andrew
loan@Neon.Stanford.EDU (James P. Loan) (02/12/91)
Thanks for the replies to my problem. As Andrew Myers pointed out, the trouble was with a bad ortho call. I outsmarted myself when subtracting 1's and adding 0.5's between getsize(), viewport(), and ortho2() calls. I'm glad I brought it up, though, because I'm using new-style polygons on a PI, but I want my code to run [the same] on all 4D machines. So thanks for pointing out the difference between drawing lines and drawing polygons. -pete loan loan@neon.stanford.edu