Rotating lines around a given vector

Started by
8 comments, last by Halsafar 18 years, 6 months ago
Picture the classic Asteroid ship in ur mind /\ The tip being the start point. I am having HUGE difficulties rotating the bloodly end points around the start point. All lines. Any help?
Advertisement
Here's one way you could do it. This is basically a matrix transformation method, but for 2d you can easily do it all in place - you don't need a matrix class.

Say your ship has a position and an angle. Also say that you've set up three points that represent your ship in local space, that is, centered at the origin and pointing down the +x axis. Something like:
Vector2 p[3];p[0].Set(10,0);p[1].Set(-10,6);p[2].Set(-10,-6);
Conceptually, what you want to do is set up a simple affine transformation matrix, like this:
[c -s tx]<br>[0  0 1 ]</pre>Where <i>s</i> and <i>c</i> are the sine and cosine of your rotation angle, and (tx,ty) is the ship position vector. In practice you can just do it in place, like this:<pre>// Remember, c++ functions take radians<br>float s = sinf(angle);<br>float c = cosf(angle);<br><br>Vector2 wp[3]; // World-space points for your ship<br>for (int i = 0; i &lt; 3; ++i) {<br>    wp<span style="font-weight:bold;">.x = c * p<span style="font-weight:bold;">.x - s * p<span style="font-weight:bold;">.y + position.x;<br>    wp<span style="font-weight:bold;">.y = s * p<span style="font-weight:bold;">.x + c * p<span style="font-weight:bold;">.y + position.y;<br>}</pre>Now you can draw your ship using the wp points. You can also use them for collision detection, or any other purpose where you need the ship geometry in world space.<br><br><!–EDIT–><span class=editedby><!–/EDIT–>[Edited by - jyk on October 7, 2005 6:15:17 PM]<!–EDIT–></span><!–/EDIT–>
In my asteroids game, the centre of the ship is the centre of the overall

/\


Just use the basic 2D rotation matrix/formula. I actually use glRotate, so OpenGL does it for me.
Thanks Jyk, that was perfect. Rating++
I may even try and work out the matrix method.

As for using openGL and its rotate function matt_j, I cannot... Java2D only, lines only.
Jyk ur method is nothing working unless I am perfectly centered at 0,0.

Any moment what so ever and any further rotation cause's all the points to go all over the place.
Quote:Original post by Halsafar
As for using openGL and its rotate function matt_j, I cannot... Java2D only, lines only.


You can use the matrix class java.awt.geom.AffineTransform
Hmmm.
That would really bottle neck the rendering routines.

See as of now I am using affinetransform to set up a user space and center 0,0... So I would need to set that for each object and rotate it before rendering.

But since no matter how hard I try my line end points keep shooting out to the middle of no where.... I'm about ready for an easier solution.


Here is the snippet which does the rotating:
-- m_vPos is a vector representing the tip where the 2 lines meet so they share that as a start point.

		Point2D rotPoints[] = new Point2D[3];		rotPoints[0] = new Point2D.Double(m_vPos.x, m_vPos.y);		rotPoints[1] = new Point2D.Double(m_linebuf[0].getX2(), m_linebuf[0].getY2());		rotPoints[2] = new Point2D.Double(m_linebuf[1].getX2(), m_linebuf[1].getY2());		// Remember, c++ functions take radians		double s = Math.sin(deg * cGameMath.TORAD); //cCircleTable.vTable[deg].y;		double c = Math.cos(deg * cGameMath.TORAD);//cCircleTable.vTable[deg].x;				Point2D wp[] = new Point2D[3];		wp[0] = new Point2D.Double();		wp[1] = new Point2D.Double();		wp[2] = new Point2D.Double();		for (int i = 0; i < 3; ++i) {			wp.setLocation(c * rotPoints.getX() - s * rotPoints.getY() + m_vPos.x,					  s * rotPoints.getX() + c * rotPoints.getY() + m_vPos.y);		}				m_linebuf[0].setLine(wp[0], wp[1]);		m_linebuf[1].setLine(wp[0], wp[2]);
That formula seems weird. Wouldn't it just be this?

for (int i = 0; i < 3; ++i) {  wp.setLocation(c * rotPoints.getX() + m_vPos.x,    s * rotPoints.getY() + m_vPos.y);		}


And if you want the sides of the ship to be longer than 1, something like this:

float line_segment_dist = 5f;for (int i = 0; i < 3; ++i) {  wp.setLocation(c * rotPoints.getX() * line_segment_dist + m_vPos.x,    s * rotPoints.getY() * line_segment_dist + m_vPos.y);		}

Quote:Jyk ur method is nothing working unless I am perfectly centered at 0,0.

Any moment what so ever and any further rotation cause's all the points to go all over the place.
I just tested the code and it works fine. I did make a mistake with the indices for p, which I've now fixed. However, it looks like you already caught that.

However, you're setting up the initial points incorrectly. I now see that this isn't entirely clear from my example, but the array p[3] is set once at the beginning of the program and never changes (unless you want to change the shape of your ship). The whole point of the affine transform is to take the ship geometry in local space, which never changes, and transform it into world space based on its position and rotation angle. So try replacing the lines:
rotPoints[0] = new Point2D.Double(m_vPos.x, m_vPos.y);rotPoints[1] = new Point2D.Double(m_linebuf[0].getX2(), m_linebuf[0].getY2());rotPoints[2] = new Point2D.Double(m_linebuf[1].getX2(), m_linebuf[1].getY2());
With something like:
rotPoints[0] = new Point2D.Double(10, 0);rotPoints[1] = new Point2D.Double(-10, 6);rotPoints[2] = new Point2D.Double(-10, -6);
With those specific values adjusted for scale and the desired shape of the ship. Note also that in your code you're setting the nose of the ship to the ship position itself, which, even if we were doing 'world space' rotations, would cause the ship to rotate about its nose - probably not what you want.

I hope that clears up the example a bit. I can practically guarantee that the method works as advertised, so I'd just stick with it until you get the bugs ironed out.
Quote:That formula seems weird.
Nevertheless, it is correct :)
It is very correct.

Yes I totally didn't catch that object space part. The clarity in your reply was perfect. I know have it all setup and she rotates fine.

Thank you.

This topic is closed to new replies.

Advertisement