Advertisement

How to fix 2D rotation distortion

Started by September 25, 2023 02:40 AM
6 comments, last by nomacaly 1 year, 2 months ago

hello is me again.

i am trying to add rotation to my graphics engine but it is not going well. when the mesh rotates it becomes distorted, my first thought was that the problem was my line drawing implementation but after changing it the problem still occurred. what can i do the solve this issue.

--Line drawing code--

static void DrawLine(i32 x0, i32 y0, i32 x1, i32 y1, u32 Color)
{int x, y, dx, dy, px, py, dx1, dy1, xe, ye;
	
	dx = x1 - x0; dy = y1 - y0;
	
	if(dx==0) //Line Vertical
	{
		if(y1 < y0)
		{
			y0 = y0 + y1;
			y1 = y0 - y1;
			y0 = y0 - y1;
		}
		
		for(y = y0; y <= y1; y++) plotPixel(x0, y, Color);
	}
	
	if(dy==0)
	{
		if(x1 < x0)
		{
			x0 = x0 + x1;
			x1 = x0 - x1;
			x0 = x0 - x1;
		}
		for(x = x0; x <= x1; x++) plotPixel(x, y0, Color);
	}
	
	dx1 = abs(dx); dy1 = abs(dy);
	px = 2 * dy1 - dx1; py = 2 * dx1 - dy1;
	
	if(dx1 >= dy1)
	{
		if(dx >= 0)
		{
			x = x0; y = y0; xe = x1;
		}else
		{
			x = x1; y = y1; xe = x0;
		}
		
		plotPixel(x,y,Color);
		
		for (int i = 0; x < xe; i++)
		{
			x = x + 1;
			if(px <= 0)
			{
				px = px + 2 * dy1;
			}else
			{
				if((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
				{
					y = y + 1;
				}else
				{
					y = y - 1;
				}
				px = px + 2 * (dy1 - dx1);
				plotPixel(x,y,Color);
			}
		}
	}else
	{
		if(dy >= 0)
		{
			x = x0; y = y0; ye = y1;
		}else
		{
			x = x1; y = y1; ye = y0;
		}
		
		plotPixel(x,y,Color);
		
		for (int i = 0; y < ye; i++)
		{
			y = y + 1;
			if(py <= 0)
			{
				py = py + 2 * dx1;
			}else
			{
				if((dx < 0 && dy < 0) || (dx > 0 && dy > 0))
				{
					x = x + 1;
				}else
				{
					x = x - 1;
				}
				py = py + 2 * (dy1 - dx1);
				plotPixel(x,y,Color);
			}
		}
	}
	
}

--Rotation & transform--

	//vecShapes[0].angle = vecShapes[0].angle + 0.1 * dt;
	
	for (int i = 0; i < 4; i++)
	{
		vecShapes[0].p_v[i] = (vec2D) 
		{
			(vecShapes[0].o_v[i].x * cosf(vecShapes[0].angle)) - (vecShapes[0].o_v[i].y * sinf(vecShapes[0].angle)) + vecShapes[0].pos.x,
			(vecShapes[0].o_v[i].x * sinf(vecShapes[0].angle)) + (vecShapes[0].o_v[i].y * cosf(vecShapes[0].angle)) + vecShapes[0].pos.y
		};
	}

--Drawing--

	for (int i = 0; i < 4; i++)
	{
		DrawLine(vecShapes[0].p_v[i].x, vecShapes[0].p_v[i].y, vecShapes[0].p_v[(i+1)%4].x,vecShapes[0].p_v[(i+1)%4].y,0xfffffff);
	}

--Without rotation--

--With rotation--

You have to make a step back.

You coded it (or thought you had), tried it, and it fails. Not fun but it happens.

The next step is to simplify the problem. Instead of making animation that demonstrates a mess but gives very little hard information, try rotating 90 degrees only (You may want to use a non-square object for that.) Dump the input numbers, dump the produced output numbers, and verify manually that it computes the right values (which is trivial for such rotations). If the answer is wrong, check the intermediate numbers used in the computation as well. Do they match your intuition,? If the result is wrong, then somewhere in the process the numbers should deviate from your expectations. When it does, fix the code and try again.

Other options are angles like 45, 30, or 60 degrees rotation. Bit more difficult, but still manageable.

Advertisement

i have tried and i have absolutely no idea how to fix it. i have crashed my computer 5 times trying to do this thing. i'm actually going to loose it

Does cosf and sinf take an input as an angle or radians? I suspect you're providing an angle and the functions are requiring radians. I've never seen cos and sin functions take an angle as an argument.

No, I am not a professional programmer. I'm just a hobbyist having fun...

First off, there appears to be a problem with your line drawing algorithm. Forget about rotation and just test drawing lines in different directions. You have a lot of conditionals in your code, and you need to test every one of them to see that they are producing the correct output.

a light breeze said:

First off, there appears to be a problem with your line drawing algorithm. Forget about rotation and just test drawing lines in different directions. You have a lot of conditionals in your code, and you need to test every one of them to see that they are producing the correct output.

Agreed. This is some modified code that I have used in the past:

#define ABS(x)		(x < 0 ? -x : x)
#define SIGN(x)		((x) < 0 ? -1 : ((x) > 0 ? 1 : 0))

void DrawLine(i32 x0, i32 y0, i32 x1, i32 y1,u32 Color)
{
	i32	dy,dx;
	i32	sx,sy;
	i32	accum;

	dx = x1 - x0;
	dy = y1 - y0;

	sx = SIGN(dx);
	sy = SIGN(dy);

	dx = ABS(dx);
	dy = ABS(dy);

	x1 += sx;
	y1 += sy;

	if(dx > dy)
	{
		accum = dx >> 1;

		do{
			plotPixel(x,y,Color);

			accum -= dy;

			if(accum < 0)
			{
				accum += dx;
				y0 += sy;
			}

			x0 += sx;
		}while(x0 != x1);
	}else{
		accum = dy >> 1;

		do{
			plotPixel(x,y,Color);

			accum -= dx;

			if(accum < 0)
			{
				accum += dy;
				x0 += sx;
			}

			y0 += sy;
		}while(y0 != y1);
	}
}

No, I am not a professional programmer. I'm just a hobbyist having fun...

Advertisement

@MarkS lol. that's almost like the first implementation, only had to make a few changes, thank you 🙂

This topic is closed to new replies.

Advertisement