Hi all,
Im trying to get my 3D sphere to rotate when a user moves their mouse/finger over the sphere.
I can get it to rotate no problems, but when I try to add inertia to the sphere using the Affine2DInertiaProcessor in the Surface SDK, I get jumping issues when I quickly flick the sphere, and I dont know why...
Here is my initialisation code:
private void InitializeManipulationProcessor()
{
manipulationProcessor = new Affine2DManipulationProcessor(
Affine2DManipulations.Rotate |
Affine2DManipulations.TranslateX |
Affine2DManipulations.TranslateY,
_eventSource);
inertiaProcessor = new Affine2DInertiaProcessor();
inertiaProcessor.Affine2DInertiaDelta += Inertia_OnManipulationDelta;
inertiaProcessor.Affine2DInertiaCompleted += InertiaProcessor_Affine2DInertiaCompleted;
manipulationProcessor.Affine2DManipulationStarted += OnManipulationStarted;
manipulationProcessor.Affine2DManipulationDelta += Manipulation_OnManipulationDelta;
manipulationProcessor.Affine2DManipulationCompleted += OnManipulationCompleted;
}
When a user moves their finger, here is the code to rotate the sphere:
private void Manipulation_OnManipulationDelta(object sender, Affine2DOperationDeltaEventArgs e)
{
Point currentPosition = e.ManipulationOrigin;
// avoid any zero axis conditions
if (currentPosition == _previousPosition2D)
return;
Track(currentPosition);
_previousPosition2D = currentPosition;
}
This starts the ineria, when the user stops moving their finger:
private void OnManipulationCompleted(object sender, Affine2DOperationCompletedEventArgs e)
{
inertiaProcessor.InitialOrigin = e.ManipulationOrigin;
inertiaProcessor.InitialVelocity = e.Velocity;
inertiaProcessor.DesiredDeceleration = 0.0001;
inertiaProcessor.Begin();
}
The magic of the rotation, happens in the Track method below:
private void Track(Point currentPosition)
{
Vector3D currentPosition3D = ProjectToTrackball(currentPosition);
Vector3D axis = Vector3D.CrossProduct(_previousPosition3D, currentPosition3D);
double angle = Vector3D.AngleBetween(_previousPosition3D, currentPosition3D);
// quaterion will throw if this happens - sometimes we can get 3D positions that
// are very similar, so we avoid the throw by doing this check and just ignoring
// the event
if (axis.Length == 0)
return;
Quaternion delta = new Quaternion(axis, -angle);
// Get the current orientantion from the RotateTransform3D
Quaternion q = new Quaternion(_rotation.Axis, _rotation.Angle);
// Compose the delta with the previous orientation
q *= delta;
// Write the new orientation back to the Rotation3D
_rotation.Axis = q.Axis;
_rotation.Angle = q.Angle;
_previousPosition3D = currentPosition3D;
}
The _rotation var is the AxisAngleRotation3D class used for the RotateTransform3D on the 3d mesh.
I know this is a specialty case, but I have a feeling that it is a calculation issue, and I really have no idea how to debug this.
One more thing, a very interesting thing to note is that if I flick the globe slowly I do NOT get any jumping and it is very smooth! So it must be something to do with either large calculations, or just some bug...
If you are good at 3D rotation and truly believe that you can help, then I will be happy to package up this project into a ZIP and send it to you if you need a better format to work with
Thanks for any help you can give, i really appreciate the help!
Mark