Skip to main content
gamedev.net
🔒 Locked

Rotation

Started by jakerrz Jan 10, 2004 at 2:13 AM 5 replies 1.4k views
Original Post
jakerrz
jakerrz
Hi I'm trying to rotate a circle, well it's a circle made out of circles that I'm creating programatically. For some reasone when I rotate my circle it gets all distorted(streached flattened) but I can't figure out why?? What I want is for the circle to rotate without loosing its shape. I Wrote this program using Allegro... here's the source sorry if it's confusing I'm just hacking on this program to try to learn stuff. I put a //NOTE comment at the part I have a question about so you can find it quickly I just thought I'd include the entire code incase someone wanted to compile it keep in mind you'll need allegro if you want to compile it.
#include <stdio.h>
#include <math.h>
#include "allegro.h"

volatile int frame_count, fps;

void fps_proc(void)
{
   fps = frame_count;
   frame_count = 0;
}

END_OF_FUNCTION(fps_proc);

int main(void)
{
	#define PI 3.14159265358979
    BITMAP *dblbuffer;
    int x;
	int i = 0;
	int theta = 0;
	int plotx, ploty;
	int rotate = 0;

	char buffer[20];
	char score_buf[80];
	frame_count = fps = 0;

    allegro_init();

    install_keyboard();
    install_timer();        /* needed for `rest' function */

    if (set_gfx_mode(GFX_AUTODETECT, 1280, 1024, 0, 0) < 0) {
	//printf("%s\n", allegro_error);

	exit(1);
    }
    clear(screen);

	/* set up the interrupt routines... */

	LOCK_VARIABLE(frame_count);
	LOCK_VARIABLE(fps);
	LOCK_FUNCTION(fps_proc);




   install_int(fps_proc, 1000);

    dblbuffer = create_bitmap(SCREEN_W, SCREEN_H);
    clear(dblbuffer);

    vsync();
    blit(dblbuffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);


	do{
	
	poll_keyboard();
	if(key[KEY_ESC])
		break;


		for (x = 0; x < 360; x++) {
		//rest(2);		/* slow it down so we can see it */

		//circlefill(dblbuffer, x - 1, 100, 50, 0);	/* erase from last place */

		//circlefill(dblbuffer, x, 450+100*( sin((x+y*90)*PI/180)) , 10, x%30 + 32 ); //sin

		//circlefill(dblbuffer, x, 450+50*( tan((x+y*90)*PI/180)) , 10, x%30 + 32 );//tan

		//putpixel(dblbuffer,x,450+100*( sin((x+y*90)*PI/180)),x%30 + 32);



			//calculate x, y for circle elements

			plotx = 300* cos(x*PI/180);
			ploty = 300* sin(x*PI/180);

			//rotate x, y 


			if(rotate > 0)
			{
//NOTE This is the part I'm having trouble with!!		

				
				plotx = (plotx * cos(theta*PI/180) - ploty * sin(theta*PI/180));
				ploty = (ploty *cos(theta*PI/180) + plotx*sin(theta*PI/180));
			}

			//shift

			plotx = plotx + SCREEN_W / 2;
			ploty = ploty + SCREEN_H / 2;

			circlefill(dblbuffer, plotx, ploty , 10, x%30 + 32 ); //sin

			poll_keyboard();
			if(key[KEY_R])
			rotate = 1;		



		
		//textout(dblbuffer, font, "Double buffering (mode 13h)", 0, 0, 15);

		
		}


		if (fps)
		sprintf(score_buf, "(%ld fps)",(long)fps);
	else
		sprintf(score_buf, "0");

	sprintf(buffer,"theta: %d degrees", theta);

	textout(dblbuffer, font, score_buf, 0, 0, 7);
	textout(dblbuffer, font, "Press R to begin Rotation", 1015, 0, 7);
	textout(dblbuffer,font,buffer,0,20,7);
	theta++;
	if(theta > 360)
		theta = 1;
	
			//vsync();

	//readkey();	

	blit(dblbuffer, screen, 0, 0, 0, 0, SCREEN_W, SCREEN_H);
	frame_count++;
	clear(dblbuffer);

	} while (!key[KEY_ESC]);

	// Now, remember to FREE the memory you previously allocated

    destroy_bitmap(dblbuffer);

    return 0;
}
END_OF_MAIN();
 
I'm looking for a solution that will allow me to rotate any graph of points. when i posted this on the allegro.cc forum I was told:
quote:
Try replacing the above with just: //calculate x, y for circle elements plotx = 300* cos((x+theta)*PI/180); ploty = 300* sin((x+theta)*PI/180);
I understand that by adding theta to x it makes the circle rotate but that isn't neccisarilly a solution for rotating other types of graphs. Say you wanted to graph y = 100*(sinx) or something like that if you put, ploty = 100*(sin(x+theta*PI/180)); then you would see the sine graph phase shifting correct? I tried nearly the same program as the original source listed with the graph of a sine wave and it also got all distoreted as I tried to rotate it. What I'd like to figure out is a way to manipulate the x and y values of the points on a graph to rotate it. Thanks so much for any help with this. -Jake [edited by - jakerrz on January 10, 2004 3:14:56 AM]
Zipster
Zipster
I'm not a big fan of using the linear combinations, so it might be a bit nicer just to do what the allegro.cc guys say and add the angles together.

Also, it would be easier to store your angles directly in radians rather than degrees, so you don't have to do the conversion all the time.

quote:
I understand that by adding theta to x it makes the circle rotate but that isn't neccisarilly a solution for rotating other types of graphs. Say you wanted to graph y = 100*(sinx) or something like that if you put, ploty = 100*(sin(x+theta*PI/180)); then you would see the sine graph phase shifting correct? I tried nearly the same program as the original source listed with the graph of a sine wave and it also got all distoreted as I tried to rotate it. What I'd like to figure out is a way to manipulate the x and y values of the points on a graph to rotate it.

Trigonometry is based around the unit circle, and since all points are equidistant from the center, it's easy to rotate things in a circular path using the method I showed you above. However, when it comes to other graphs, you're either stuck using a linear combination each iteration to update the position, which can slowly destroy the data like it did for you, or find the distance and angle of each point on the graph from the center and replot it completely.

For example, for any point on the function 100sin(x), the distance from the origin is sqrt(x2 + 10000sin2(x)). So if you wanted to rotate that graph by theta, you'd have to replot each point using basically what we did above. You have to know the initial angle each point was at (the positional angle I described it as above), so you know the effective angle or rotation:

// max is the absolute domain you want to use
for(x = -max; x < max; ++x)
{
// Angle this point is at already
float angle = atan2(100sin(x),x);
// Adjust range
angle = (angle < 0) ? angle + 2*PI : angle;

// Rotate by theta at distance
plotx = sqrt(x*x + 10000*sin(x)*sin(x))*cos(angle + theta);
ploty = sqrt(x*x + 10000*sin(x)*sin(x))*sin(angle + theta);

// Center screen
plotx += SCREEN_W / 2;
ploty += SCREEN_H / 2;

// Plot point here
}


[edited by - Zipster on January 10, 2004 5:59:29 AM]
jakerrz
jakerrz
Wow, thanks a lot for that reply and explanation... I just realized I understand much less of this math then I thought but I'll keep working at it. I wish I could understand why the formulas I'm using don't work. It doesn't really make sense to me that the data should become corrupt slowly as i process it because I'm recomputing the starting x,y values and then applying a rotation to those. I've seen this same method used in many tutorials on rotating polygons etc... And could't you think of the graph of y = 100*sin(x) as a polygon with so many hundred/thousand points?? why shouldn't it work exactly the same as rotating a simple polygon.

I guess I'll just have to experiment with some more code when I get home... I'm at my girlfriends now and don't have an ide or anything installed on her computer...

edit: Ok I was given the solution by Krajzega on the allegro.cc forum for anyone that's interested here's what he said...

quote:

Your image gets distorted because you use un-rotated coordinates in the first line (calcualting x), but in the second you try to calculate a rotation of a point that has y coordinate unrotated, and the x one - rotated. That's why your image get's distorted with the universal formula.

Try storing the original x in a variable and use that instead of the plotx in the second line.

Like:


storedx = plotx;
plotx = (plotx * cos(theta*PI/180) - ploty * sin(theta*PI/180));
ploty = (ploty *cos(theta*PI/180) + storedx*sin(theta*PI/180));



[edited by - Jakerrz on January 10, 2004 6:59:57 PM]
Thunder_Hawk
Thunder_Hawk
Zipster, your method, while not obvious at all, contains many trigonometric redundancies. If you want to see why, try working the problem without starting by numerically finding the original angle.

______________________________________________________________
The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ
MySite
______________________________________________________________
______________________________________________________________________________________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 Forma
Zipster
Zipster
I don''t doubt it does. But when I''m thinking off the top of my head, I take logic and convert it into math. Then I go back and fix it up.

But I''m not the one who is coding this. Thus it''s not up to me to optimize everything.
Thunder_Hawk
Thunder_Hawk
I''ve got no problem with that. That''s about the most efficient and productive way to code after all . But having worked this problem before, I thought you might be interested to see how these two methods that look very little alike could produce the same result.

______________________________________________________________
The Phoenix shall arise from the ashes... ThunderHawk -- ¦þ
MySite
______________________________________________________________
______________________________________________________________________________________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 Forma
Zipster
Zipster
Well, especially with trigonometry there are always many different ways to accomplish things with all the different identities. But what I know I hate doing is adding sine and cosine unless they''re squared

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.