Rotate with an offset

Discuss any questions about BEPUphysics or problems encountered.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotate with an offset

Post by Norbo »

I would recommend stepping through the code line by line, examining the Translation property of the transform and comparing it against your expectations after each transform application. Since it's a centralized and simple sequence of transformations, it should be fairly easy to identify where it goes awry.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Rotate with an offset

Post by snoozbuster »

I'm not seeing it. Is it something with CreateFromQuaternion that's ignoring the offset somehow? That doesn't make sense, but it seems like the only thing that might be it. The LinearVelocity as (goal - currentPosition) * space.TimeStepSettings.TimeStepDuration is always far too small, it's in the 0.05-0.08 range, but I don't know why that would be. Like I said, it also has that drift, which I can't find the cause of anywhere. It's all so bothersome. It seems to me like it should work, but something isn't. I think it's primarily an issue with the LinearVelocity, which means there's a problem with either the translation's calculation or the velocity's calculation.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotate with an offset

Post by Norbo »

To span the gap of (goal-position) in one frame, it should be divided by dt, not multiplied- so that's one thing :)
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Rotate with an offset

Post by snoozbuster »

That makes a velocity in the 200s... I'll try it. Yeah. I'm certain there's something wrong with the way I'm doing translation. I have no idea what it might be, though.

le EDIT: newOrientation.CreateTranslation(m.Origin) is the issue. Without it, everything operates exactly as it should, just in the wrong spot. I realized my (goal - position) / dt was actually (position - goal) / dt, and switching that around fixed it mostly. Origin (the spot the model starts in and is reset to) doesn't work there, Position doesn't work there (flies off into the distance)... I don't have any idea what the correct value is for that line.

Behavior without extra translation: Works exactly as intended, however, in the wrong spot.
Behavior with extra translation: Offset is one unit too large, offset appears to have incorrect effect on rotation (for example, if the tubes are offset on Y to start with, that same offset will still be there after rotation. I've got time, I'll make a video (but you'll have to bear with my laggy screencapping and my use of Windows Live Movie Maker. A poor Celeron 900 with a measly 10GB of disk space and 2GB of RAM can't really screencap 1280x720 well). http://dl.dropbox.com/u/33703202/demonstration.mp4 There you are. I even added text, but you might have to pause it to read one of the captions. It goes by a bit quick. Hopefully you will see what's so confounding. The first scene is without newOrientation.CreateTranslation(m.Origin), the second is with it.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotate with an offset

Post by Norbo »

A transform could be out of order or the value used to construct the transform could be wrong. Visualize the process step by step. Stepping through with the debugger and very carefully checking every value against your expectations is one approach. Another approach is to only do parts of the transformation sequence and watch them run. Compare the results with your expectations for the enabled transforms.

The key is to have well-formed expectations about what the results should be at intermediate times in the transformation sequence. Work through the sequence on paper conceptually to establish the 'control' process and then see if your control process matches the implementation.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Rotate with an offset

Post by snoozbuster »

The moment of truth! It was, in fact, an improper value passed into the last CreateTranslation. Let me explain.

I knew I had to translate the model to its proper position in worldspace, but using CreateTranslation(entity.Position) caused the entity to fly off in the direction of the offset. I figured using Origin, the point at which they started at, would work. However, this didn't account for any of the LinearVelocity changes, so they conflicted and generally didn't work. In a flash of brillance caused by itchy knees (that's a joke), I thought, "if entity.Position causes the velocity to scream off in the direction of LocalOffset, then LocalOffset is being applied twice - first by the translation of LocalOffset, and then by the translation of Position." Which makes sense sort of. After a couple of failed tries, I finally discovered the proper value for CreateTranslation: entity.Position - LocalOffset. I don't know exactly why it works this way, but it works perfectly. Well, actually I haven't tested it with the rotation of the tubes, but I can't see that being a big deal, due to the matrix system I have.

I thank you greatly for your help, and I shall report back sometime tomorrow with the success of it all.

Now to find out why two of my meshs aren't actually at the origin when my modeling program assures me they are. =D
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Rotate with an offset

Post by snoozbuster »

Well, the rollers don't roll. I've determined that the cause is that no matter what angle or axis I specify rotation on, by the time of decomposition the W component of the Quaternion is very close to 1, and ends up getting to 1 in GetAngularVelocity. I tested it when the rollers aren't rotating from the spinny spinner, and even though there is no other rotation or translation that would interfere with the rotation of the roller, it doesn't work. Do you know why this might be? I manged to get it to rotate kinda, but it just jittered and then stopped when the spinny part rotated. I have CreateRotationY(MathHelper.TwoPi / dt) as the first thing I do, and I've tried * dt, variations of pi, 45 degrees, and so on... But it always goes poof by the end, whether or not there's other rotation. My code is:

Code: Select all

foreach(Tube t in tubeList)
{
    newOrientation = Matrix.Identity;

    if(t.Rotating)
        newOrientation *= Matrix.CreateRotationY(MathHelper.TwoPi / BaseGame.space.TimeStepSettings.TimeStepDuration);

    newOrientation *= Matrix.CreateFromQuaternion(t.OriginalOrientation);

    newOrientation *= Matrix.CreateTranslation(t.LocalOffset);

    newOrientation *= Matrix.CreateFromQuaternion(curve.Evaluate(pathTime));

    newOrientation *= Matrix.CreateTranslation(t.Origin - t.LocalOffset);
    newOrientation.Decompose(out scale, out rotation, out translation);
                
    t.Ent.AngularVelocity = GetAngularVelocity(t.Ent.Orientation, rotation, BaseGame.space.TimeStepSettings.TimeStepDuration);

    t.Ent.LinearVelocity = (translation - t.Ent.Position) / (float)BaseGame.space.TimeStepSettings.TimeStepDuration;
}
The local rotation around Down should be the first thing done, and it's faster to do a rotation around the axis all rollers start out aligned with and then go from there. However, I tried creating a new Quaternion with one frame's rolling and the rotation of the matrix concatenated, and the same thing happened. In fact, no matter what value goes there, it seems to take effect for the single frame I used Edit and Continue, and after that it goes back to normal. I've taken to just commenting out the if statement for testing, and threw in some massive values for testing, and lo and behold... Nothing. 100 radians really should do something. Normally, the rotation for a roller is handled with AngularVelocity = OrientationMatrix.Down * TwoPi... *sighs* I just have no idea what to do.
Norbo
Site Admin
Posts: 4929
Joined: Tue Jul 04, 2006 4:45 am

Re: Rotate with an offset

Post by Norbo »

For default values, MathHelper.TwoPi / timeStepDuration = MathHelper.TwoPi / (1/60) = MathHelper.TwoPi * 60 ~= 0 radians. If you'd like to rotate TwoPi radians in one second, then there should be a rotation of TwoPi * dt radians each frame.

It looks like the reason it doesn't change is that the target roll never changes. If every frame you take the identity orientation and multiply it by some fixed rotation, you will end up with the fixed rotation every frame. Since the entity's already at the goal, subsequent frames will not try to apply any additional roll.
snoozbuster
Posts: 172
Joined: Sat Sep 24, 2011 7:31 am

Re: Rotate with an offset

Post by snoozbuster »

Norbo wrote:For default values, MathHelper.TwoPi / timeStepDuration = MathHelper.TwoPi / (1/60) = MathHelper.TwoPi * 60 ~= 0 radians. If you'd like to rotate TwoPi radians in one second, then there should be a rotation of TwoPi * dt radians each frame.

It looks like the reason it doesn't change is that the target roll never changes. If every frame you take the identity orientation and multiply it by some fixed rotation, you will end up with the fixed rotation every frame. Since the entity's already at the goal, subsequent frames will not try to apply any additional roll.
I had TwoPi * dt, but that didn't work either.

That makes sense. Now I guess I get to do things a little differently... Ah well. =p
Post Reply