Jump to content

  • Log In with Google      Sign In   
  • Create Account

Image not rotating properly (using Matrix)


Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

  • You cannot reply to this topic
2 replies to this topic

#1 SirKGM   Members   -  Reputation: 118

Like
0Likes
Like

Posted 02 April 2014 - 09:08 PM

I've been trying to set up a Sprite class but am having trouble with getting the image to rotate around its center. The scaling and translation works fine but the image gets rotated around in a wide arc instead of around the center. I've run this through the debugger and everything else works as it should but for some reason the rotation doesn't work.

public class DSprite extends Sprite {
	Matrix matRotation;
	Matrix matTranslation;
	Matrix matScale;
	Matrix matTotal;
	Paint alpha;
	float centerX;
	float centerY;
	float scaleX;
	float scaleY;
	float rotation;
	
	public DSprite(Image image, float pctX, float pctY) {
		super(image, pctX, pctY);
		centerX = getCenterX();
		centerY = getCenterY();
		
		scaleX = 1f;
		scaleY = 1f;
		rotation = 0;
		
		matRotation = new Matrix();
		matTranslation = new Matrix();
		matScale = new Matrix();
		matTotal = new Matrix();
		alpha = new Paint();
	}
	
	public void draw(Canvas canvas) {
		matScale = new Matrix();
		matScale.setScale(scaleX, scaleY);
		
		matRotation = new Matrix();
		matRotation.setRotate(rotation, centerX, centerY);
		
		matTranslation = new Matrix();
		matTranslation.setTranslate(x, y);
		
		matTotal = new Matrix();
		matTotal.postConcat(matScale);
		matTotal.postConcat(matRotation);
		matTotal.postConcat(matTranslation);
		
		canvas.drawBitmap(image.bitmap, matTotal, alpha);
	}
	
	public void rotate(float degrees, boolean reset) {
		if (reset) { rotation = 0; }
		rotation += degrees;
	}

	public void scale(float scaleX, float scaleY) {
		this.scaleX = scaleX;
		this.scaleY = scaleY;
	}

	public float getCenterX() {
		centerX = x + (image.bitmap.getWidth() / 2);
		return centerX;
	}
	
	public float getCenterY() {
		centerY = y + (image.bitmap.getHeight() / 2);
		return centerY;
	}
}



Sponsor:

#2 haegarr   Crossbones+   -  Reputation: 4602

Like
1Likes
Like

Posted 03 April 2014 - 12:57 AM

In 2D the one and only fix point in rotation is (0,0). So you need to shift your desired center of rotation to (0,0), and perform the rotation in this shifted space. However, you do not actually want the sprite be located where shifted to, so you need to undo the shift onto the rotated result.

 

In your case, shifting and rotation and undo shifting is implemented inside

    matRotation.setRotate(rotation, centerX, centerY);

 

However, the computation of centerX and centerY considers the global positioning vector (x,y), but at the moment when you apply the rotation, the current space is not what you would call the world. In other words, the sprite is not just translated to its world position, but the rotation expects that it is.

 

Hence the solution is to use the center of the sprite not in global space but in the space active after scaling is applied (because that is the space where the rotation matrix is calculated). That means

    rotCenterX = image.bitmap.getWidth() / 2;

    rotCenterY = image.bitmap.getHeight() / 2;

(notice the lack of x and y), so that the rotation matrix becomes computed by

    matRotation.setRotate(rotation, rotCenterX, rotCenterY);

 

(You may use centerX and centerY by adapting the respective routines, of course, if they are not used otherwise to actually return the global center.)


Edited by haegarr, 03 April 2014 - 01:01 AM.


#3 SirKGM   Members   -  Reputation: 118

Like
0Likes
Like

Posted 03 April 2014 - 08:22 PM

Thank you so much! I did a lot of googling and hacking to try to find what was happening, and I can't believe I didn't come across this. Great explanation, thanks again.






Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.



PARTNERS