|
CharsAce
|
 |
« on: July 05, 2012, 05:04:00 PM » |
|
I am having a problem when rotating a rectangle. I construct the rectangle from points. When I want to rotate the rectangle the points seem to shift a little bit. How can I keep this from happening?
|
|
|
|
|
Logged
|
|
|
|
|
Nix
|
 |
« Reply #1 on: July 05, 2012, 05:14:55 PM » |
|
That question is impossible to answer in any way except "you're doing it wrong." Why don't you post your current calculations.
|
|
|
|
|
Logged
|
|
|
|
|
CharsAce
|
 |
« Reply #2 on: July 05, 2012, 05:25:34 PM » |
|
That question is impossible to answer in any way except "you're doing it wrong." Why don't you post your current calculations.
//where rectangle points are stored public Vector2 Position; public Vector2 TopRight; public Vector2 BottomRight; public Vector2 BottomLeft;
//Point rectangle is rotated around Vector2 rotationPoint;
//rotates a point around a point public static Vector2 RotatePoint(Vector2 point, Vector2 origin, float rotation) { Vector2 difference = point - origin;
//if (difference==Vector2.Zero) //{ // return point; //} Vector2 rotatedPoint = Vector2.Transform(difference, Matrix.CreateRotationZ(rotation));
return rotatedPoint + origin; }
There it is. I was thinking of maybe having constraints for the length of the edges?
|
|
|
|
|
Logged
|
|
|
|
|
epcc
|
 |
« Reply #3 on: July 05, 2012, 05:43:51 PM » |
|
i guess it's some kind of a floating point rounding error that accumulates over time. to avoid that, store your vertices relative to the body and every time that body's transform is changed, recalculate the global coordinates.
that is assuming you are absolutely confident in your vector routines and that you aren't doing it already.
|
|
|
|
|
Logged
|
|
|
|
|
Nix
|
 |
« Reply #4 on: July 05, 2012, 05:56:44 PM » |
|
I doubt floating point errors would be able to accumulate quickly enough to cause noticeable drift. You should also share the code which is calling the rotation function.
Edit: you should also make a video or something of what's going on. I may be misunderstanding the problem
|
|
|
|
|
Logged
|
|
|
|
|
bateleur
|
 |
« Reply #5 on: July 06, 2012, 03:15:11 AM » |
|
Whilst the problem may or may not be rounding error there's no reason to ever write code in which this can happen. Store the current angle separately from the transformed point and find the new position by transforming a fixed start position. That way, errors can't build up.
My wild guess for what's going on in this case is that probably you have an int somewhere (maybe just an implicit cast) and your floats are being repeatedly rounded to ints.
|
|
|
|
|
Logged
|
|
|
|
|
Netsu
|
 |
« Reply #6 on: July 06, 2012, 03:23:06 AM » |
|
Whilst the problem may or may not be rounding error there's no reason to ever write code in which this can happen. Store the current angle separately from the transformed point and find the new position by transforming a fixed start position. That way, errors can't build up.
My wild guess for what's going on in this case is that probably you have an int somewhere (maybe just an implicit cast) and your floats are being repeatedly rounded to ints.
It doesn't need to have anything to do with ints. It's perfectly normal for floats to accumulate errors during such calculations, even a few hundred iterations could be enough to completely deform a geometric shape. So yeah, always store points (which never change) and angle separately and compute the rotated shape only when it is needed (which is probably collision detection and drawing). The same goes for points and position offset of your figure, although addition and subtraction aren't subject to such errors as multiplication and division.
|
|
|
|
|
Logged
|
|
|
|
|
Nix
|
 |
« Reply #7 on: July 06, 2012, 03:26:47 AM » |
|
I think you're all crazy
|
|
|
|
|
Logged
|
|
|
|
|
Netsu
|
 |
« Reply #8 on: July 06, 2012, 03:31:44 AM » |
|
Seriously, I had the same problem and many wise wizards told me the same thing 
|
|
|
|
|
Logged
|
|
|
|
|
Fallsburg
|
 |
« Reply #9 on: July 06, 2012, 06:24:15 AM » |
|
Well you only posted a small portion of your code, how about sharing: Vector2.Transform
and Matrix.CreateRotationZ()
|
|
|
|
|
Logged
|
|
|
|
|
CharsAce
|
 |
« Reply #10 on: July 06, 2012, 08:33:01 AM » |
|
Well you only posted a small portion of your code, how about sharing: Vector2.Transform
and Matrix.CreateRotationZ()
I'm using xna. Those classes are a part of the xna framework. I will post a video today.
|
|
|
|
|
Logged
|
|
|
|
|
|
|
Netsu
|
 |
« Reply #12 on: July 06, 2012, 11:33:39 AM » |
|
This is weird, I thought the rectangle is deforming, but there is just an angle error. This rather rules out what I and others have suggested.
|
|
|
|
|
Logged
|
|
|
|
|
CharsAce
|
 |
« Reply #13 on: July 06, 2012, 12:00:29 PM » |
|
This is weird, I thought the rectangle is deforming, but there is just an angle error. This rather rules out what I and others have suggested.
I am guessing it is a floating point error. 1.57r = 89.954373835539243776573103058145 degrees. 90 degrees = 1.5707963267948966192313216916398r.
|
|
|
|
|
Logged
|
|
|
|
|
Netsu
|
 |
« Reply #14 on: July 06, 2012, 12:25:04 PM » |
|
I still think you should try storing points and angles separately, even if it will not solve this problem (though it might) it can save you problems in the future.
|
|
|
|
|
Logged
|
|
|
|
|
Fallsburg
|
 |
« Reply #15 on: July 06, 2012, 01:04:13 PM » |
|
It's not a floating point error, it's the fact that you are using the wrong freaking number (unless you were just reducing precision in your stating it here).
You are using a number that is ~0.056% off which is ~1e12 worse than the errors that would happen naturally due to floating point precision loss (per calculation). So your errors are going to accumulate very, very quickly (i.e. we can see it) instead of slowly (i.e. possibly still a problem, so much less of a problem).
|
|
|
|
|
Logged
|
|
|
|
|
CharsAce
|
 |
« Reply #16 on: July 06, 2012, 03:15:25 PM » |
|
It's not a floating point error, it's the fact that you are using the wrong freaking number (unless you were just reducing precision in your stating it here).
You are using a number that is ~0.056% off which is ~1e12 worse than the errors that would happen naturally due to floating point precision loss (per calculation). So your errors are going to accumulate very, very quickly (i.e. we can see it) instead of slowly (i.e. possibly still a problem, so much less of a problem).
It is my fault, but it is a percision error, caused by me.  I still think you should try storing points and angles separately, even if it will not solve this problem (though it might) it can save you problems in the future.
This would need another set of points though right? Because it doesn't make sense to rotate the points every time I draw them to screen.
|
|
|
|
|
Logged
|
|
|
|
|
BWG
|
 |
« Reply #17 on: July 06, 2012, 03:30:25 PM » |
|
It seems to me that your problem is not in the drift of the points, it's the drift of angle. You are using radians (well done) but remember pi is a transcendental number so you can never be too exact. I assume you do something like this: float angle = 0.0; loop { drawbox(angle) angle += pi/2 }
Instead, do this: int quarter_revs = 0; loop { float angle = float(quarter_revs)*(pi/2) drawbox(angle) }
Then you wont get drift on the angle
|
|
|
|
|
Logged
|
|
|
|
|
CharsAce
|
 |
« Reply #18 on: July 06, 2012, 03:40:44 PM » |
|
It seems to me that your problem is not in the drift of the points, it's the drift of angle. You are using radians (well done) but remember pi is a transcendental number so you can never be too exact. I assume you do something like this: float angle = 0.0; loop { drawbox(angle) angle += pi/2 }
Instead, do this: int quarter_revs = 0; loop { float angle = float(quarter_revs)*(pi/2) drawbox(angle) }
Then you wont get drift on the angle Ok, you're gonna have to explain what's happening in your code. Why multiply pi/2 by zero?
|
|
|
|
|
Logged
|
|
|
|
|
BWG
|
 |
« Reply #19 on: July 06, 2012, 05:02:06 PM » |
|
oops, what an idiot I am! I forgot to add a line: int quarter_revs = 0; loop { float angle = float(quarter_revs)*(pi/2) drawbox(angle) quarter_revs++ }
The quarter revs specifies how many quarter turns you want to perform, it should increment each frame (I'm taking your video as a guide). So, as you know pi/2 radians is the same as 90 degrees. But since we cant represent pi faithfully, the first snippet of code is accumulating the error. The second snippet is better because you are only using pi once to calculate the angle. It is used in a direct calculation, not in an iterative manner. If you prefer to work in degrees, it would look like this (since at some point you have to convert to radians anyway): float angle_degrees = 0.0; loop { float angle_radians = angle_degrees*(pi/180) drawbox(angle_radians) angle_degrees += 90.0 }
Hope thats clearer. Sorry about the mistake.
|
|
|
|
|
Logged
|
|
|
|
|