2D rotation - polygon points don't rotate in unison (and size fluctuates)

Started by
7 comments, last by sheh 19 years, 7 months ago
Hello. I'm trying to rotate 2D polygons. The polygons are drawn with standard library/API line routines, and no anti-aliasing. It's working, but the vertexes (I don't like vertices :) don't move in complete unison, which causes polygons to distort a bit, and also to grow/shrink by 1 pixel at times, depending on the shape and position. My test program is an analog watch. When the hands rotate, they seem to distort and swim instead of moving like solid objects. When tracing the path a rotated point takes, the plotted circle is not ideal -- some of its edges are 2 pixel wide, which may explain the size fluctuation, and also why small rotation increments causes some points to seem to "stick" in the same place while others move on. This explanation may not be clear enough, so have a look at http://members.fortunecity.com/xgt/rot.htm for a visual explanation of the non-ideal "point rotation trace". Also there is a DOS executable showing the problem in action. I'm doing the rotation the standard way, always calculating from the original data, and by now I'm using fixed point. What am I missing? Ehud. [Edited by - sheh on September 1, 2004 8:47:36 AM]
Advertisement
Well, I can only guess because you didn't post the code, so..
  • You may be rotating around the wrong axis

...

Can't come up with anything else right now, and I don't think even that applies because you don't seem to be using a 3D API.

So without more info, can't really do much, but..

Quote:the plotted circle is not ideal


Why don't you use some trig to rotate the coordinates (as opposed to precalcing it)? Since you're just rotating a polygon around a single point, 1 vertex will be stationary, and the other 2 will have constant radii:
n| 2|/ \1---3

Where 1 is constant, (what was the special character for theta?)

the x coords are:
sin(angle) * Radius + x-value of 1

the y coords are:
cos(angle) * Radius + y-value of 1

where angle = the angle (in Radians) formed by n-1-2 and n-1-3.
the radius is the preset distance between 1-2 and 1-3, to be used with their respective angles.

and that should rotate your polygon.
You are trying to draw the clock at too low of a resolution. The solution is either to increase the resolution at which you are drawing or to "fake" increasing the resolution by using anti-aliasing.
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
I've added to the URL posted above an animated GIF showing it in action. The size fluctuation isn't as obvious, but the "swimming" is visible. In real life usage it's more disturbing than in the animation.

@Mushu:

Quote:use some trig to rotate the coordinates as opposed to precalcing it


What do you mean instead of precalcing it? The only thing precalculated is the sine table. I'm not sure I get what you are suggesting, if it's defining the shape data using polar coordinates instead of cartesian, I tried that to no avail.

And I didn't think such a simple thing deserves code pasting, but since you brought it up... :)

Sine table is built with:
fullrad# = ATN(1) * 8scale& = 2 ^ 20divs = 256DIM sint(0 TO divs - 1) AS LONGFOR c = 0 TO divs - 1  sint(c) = SIN(fullrad# * c / divs) * scale&NEXT


Rotation looks like...
  // sidx and cidx are indexes to current angle sine a cosine  for (int c=0; c<items; c++) {    x = px[c]*sine[cidx] - py[c]*sine[sidx];    y = py[c]*sine[cidx] + px[c]*sine[sidx];    if (x<0) {      x = 1 + ~x;      x >>= 20;      x = 1 + ~x;    } else {      x >>= 20;    }    // plux, same deal for y    px[c] = xo + x;    py[c] = yo + y;  }


@Thunder_Hawk:

I'm pretty sure I saw 2D rotation working correctly even in low-res. I don't mind the aliasing, just the out-of-place vertexes, and the "size popping".
Quote:Original post by sheh
@Thunder_Hawk:

I'm pretty sure I saw 2D rotation working correctly even in low-res. I don't mind the aliasing, just the out-of-place vertexes, and the "size popping".


Perhaps I'm using the terminology in a strange way here, but the "size popping" and out-of-place vertices are a result of aliasing. It just happens that the positions of the vertices are being rounded off in much the same way that the positions of the pixels on the lines are being rounded off (commonly known as aliasing).
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
No obvious mistakes. That looks very normal for a transformation at that screen resolution. It is only due to the granularity of the pixels that any distortion occurs. "bilinear interpolation" is a common software solution for this problem.

Edit: Actually bilinear interpolation is more useful for rotating pixel buffers. If you are rotating vertices, you may just want to look-up aliased line drawing.
Bit off topic but somewhat related.

What's the best way to go about doing the rotations?

I have heard about the Gimbal's (spelling) Lock, so calculating from the orginal data using angle might not be too good.But also I have read that when doing rotation you best keep the orginal values.why? and if so when will you use it?


Btw,sheh,if you would to try a GUI alternative to Mode13h, then check out GCL.It's very easy porting vga/svga programs to GCL.But right now it lacks 1 thing very important.Lots of Colors.I havent written any code for setting the pallete yet.

The screenshot on the page with the shaded cube was done with Steel's SVGA code by just chaging the double buffer pointer.
Also,Anybody has any suggestions for setting the GDI pallete?
______________________________________________________________________________________________________
[AirBash.com]
Gimbal lock is only an issue when you are trying to represent an object's orientation using several angles along different axes. As for storing the original values, that's standard practice to improve the accuracy of any form of interpolation (i.e. make sure that it ends up in the right spot).
______________________________________________________________________________________The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ"So. Any n00bs need some pointers? I have a std::vector<n00b*> right here..." - ZahlmanMySite | Forum FAQ | File Formats______________________________________________________________________________________
Quote:GUI alternative to Mode13h

Nah, I don't use DOS except for quick tests (and some text file processing).

Anyway, maybe I'm mistaken, and that's how 2D rotation is, but I may have found another solution (although I still feel like I'm missing some way to improve things); check out the SVG clock at http://homepage.mac.com/pete.boardman/24hourclock/downloads/clock.svg (right click and uncheck high-quality mode to disable AA).

It moves smoothly without AA too. I think this may be subpixel accuracy -- feeding the fractional part to a Bresenham line drawer, instead of using a fixed fraction at beginning of lines.

This is something I should check later, but it won't help with my current target platform which is low on processing power and does not provide efficient pixel-level drawing.

For now, I think I'll leave things as they are and move on. :)

Thank you all for the help.

This topic is closed to new replies.

Advertisement