question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

I can't get my Projection Matrix to have a proper perspective for a Rotation animation

See original GitHub issue

Im trying to replicate a plane projection rotation in UWP using the composition api. But I'm having trouble with a projection matrix in my composition code. Heres what I have:

private void Perspective(FrameworkElement element, double duration, float rotationDepth = 750f)
{
    var parent = ElementCompositionPreview.GetElementVisual(element.Parent as FrameworkElement);

    var width = (float)element.ActualWidth;
    var height = (float)element.ActualHeight;
    var halfWidth = (float)(width / 2.0);
    var halfHeight = (float)(height / 2.0);

    // Initialize the Compositor
    var visual = ElementCompositionPreview.GetElementVisual(element);

    // Create Scoped batch for animations
    var batch = visual.Compositor.CreateScopedBatch(CompositionBatchTypes.Animation);

    // Rotation animation
    var projectionMatrix = new Matrix4x4(1, 0, 0, 0,
                                            0, 1, 0, 0,
                                            0, 0, 1, 1 / rotationDepth,
                                            0, 0, 0, 1);

    // To ensure that the rotation occurs through the center of the visual rather than the
    // left edge, pre-multiply the rotation matrix with a translation that logically shifts
    // the axis to the point of rotation, then restore the original location
    parent.TransformMatrix = Matrix4x4.CreateTranslation(-halfWidth, -halfHeight, 0) *
                            projectionMatrix *
                            Matrix4x4.CreateTranslation(halfWidth, halfHeight, 0);

    // Rotate along the Y-axis
    visual.RotationAxis = new Vector3(0, 1, 0);
    visual.CenterPoint = new Vector3(halfWidth, halfHeight, 0f);
    visual.RotationAngleInDegrees = 0.0f;

    var rotateAnimation = visual.Compositor.CreateScalarKeyFrameAnimation();

    rotateAnimation.InsertKeyFrame(0.0f, 90);
    rotateAnimation.InsertKeyFrame(1f, 0);
    rotateAnimation.Duration = TimeSpan.FromMilliseconds(duration);

    visual.StartAnimation("RotationAngleInDegrees", rotateAnimation);

    // Batch is ended an no objects can be added
    batch.End();
}

So this code above will rotate along the Y-axis. In the gif below, you’ll see that I have it animating on top of another animation which is driven by a PlaneProjection for comparison:

enter image description here

The “perspective” of both is fine, both in the middle. Now lets change this line of code to switch it for a rotation on the X-axis:

// Rotate along the Y-axis
visual.RotationAxis = new Vector3(0, 1, 0);

Now notice the gif below:

enter image description here

The composition animation seems to rotate with a perspective that`s more towards the right and not perfectly centered. Does my projection matrix need to change?

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (2 by maintainers)

github_iconTop GitHub Comments

1reaction
robmikhcommented, Oct 10, 2019

The issue has to do with the transform you’re manipulating on the parent. The StackPanel that gets picked up by element.Parent has an existing transform for layout purposes (e.g. VerticalAlignment="Center"), which can cause issues. This is another flavor of XAML-Composition interop friction, which you can read more about the general case here and here.

However this is certainly a strange variant, it had me stumped for a bit! I’m not entirely sure what’s going on, but it has to do with manipulating the transform of your StackPanel. Thankfully, the usual remedies apply here. To get your code working, I modified your MainPage.xaml:

<StackPanel VerticalAlignment="Center">
    <Canvas Width="300" Height="250" Margin="0,0,0,40">
        <Border Width="300"
			Height="250"
			Background="LightSeaGreen"
			x:Name="Persp">
            <TextBlock Text="Composition"
				   FontSize="28"
				   HorizontalAlignment="Center"
				   VerticalAlignment="Center"
				   FontWeight="Bold"
				   Foreground="White" />
        </Border>
    </Canvas>


    <Border Width="300"
			Height="250"
			Background="LightCoral"
			x:Name="Proj">
		<Border.RenderTransform>
			<CompositeTransform />
		</Border.RenderTransform>
		<Border.Projection>
			<PlaneProjection CenterOfRotationX="0.5" CenterOfRotationY="0.5" />
		</Border.Projection>

		<TextBlock Text="PlaneProjection"
				   FontSize="28"
				   HorizontalAlignment="Center"
				   VerticalAlignment="Center"
				   FontWeight="Bold"
				   Foreground="White" />
	</Border>
</StackPanel>

By manipulating the transform of the Canvas instead of the StackPanel, you should be able to avoid interference.

Let me know if that works for you!

0reactions
robmikhcommented, Oct 10, 2019

Glad it worked out 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

uwp - I can't get my Projection Matrix to have a proper ...
The composition animation seems to rotate with a perspective that`s more towards the right and not perfectly centered. Does my projection matrix ......
Read more >
Coding Challenge #112: 3D Rendering with Rotation and ...
7:50 Add a projection matrix 12:00 Add a rotation matrix 18:02 Make a cube with 8 points 20:41 Normalize the cube 21:45 Connect...
Read more >
How can I have a custom projection matrix? [duplicate]
short answer is no, you cant set a custom projection matrix, however added an answer to the question this is marked as a...
Read more >
Modern OpenGL 03 - Matrices, Depth Buffering, Animation
Fortunately glm::perspective can be used as a replacement. The first argument to glm::perspective is the “field of view” argument.
Read more >
Scripting API: Camera.projectionMatrix
This property is used by Unity's water rendering to setup an oblique projection matrix. Using custom projections requires good knowledge of transformation and ......
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found