我无法让我的投影矩阵为旋转动画提供正确的视角
I can't get my Projection Matrix to have a proper perspective for a Rotation animation
我m 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. Here
我有:
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();
}
所以上面这段代码会沿Y轴旋转。在下面的 gif 中,您会看到我在另一个由 PlaneProjection 驱动的动画之上制作动画以进行比较:
两者的"perspective"都很好,都在中间。现在让我们更改这行代码以将其切换为在 X 轴上旋转:
// Rotate along the Y-axis
visual.RotationAxis = new Vector3(0, 1, 0);
现在请注意下面的 gif:
合成动画似乎在旋转,视角更偏右,而不是完全居中。我的投影矩阵需要改变吗?
快速回答。
yourVisual.Offset = new Vector3((float)Window.Current.Bounds.Width / 2, (float)Window.Current.Bounds.Height / 2, 0);
这样就可以了。应用了变换矩阵的移位视觉对象。
没有它,你的视角中心是左上角。
终于得到修复,如前所述 here,只需用容器包装受影响的控件即可解决问题:
所以在我的 Xaml 我有:
<Border Width="300"
Height="250"
Background="LightSeaGreen"
x:Name="Persp"
Margin="0,0,0,40">
<TextBlock Text="Composition"
FontSize="28"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Foreground="White" />
</Border>
我改成了:
<Border Width="300"
Height="250">
<Border Background="LightSeaGreen"
x:Name="Persp"
Margin="0,0,0,40">
<TextBlock Text="Composition"
FontSize="28"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Foreground="White" />
</Border>
</Border>
我m 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. Here
我有:
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();
}
所以上面这段代码会沿Y轴旋转。在下面的 gif 中,您会看到我在另一个由 PlaneProjection 驱动的动画之上制作动画以进行比较:
两者的"perspective"都很好,都在中间。现在让我们更改这行代码以将其切换为在 X 轴上旋转:
// Rotate along the Y-axis
visual.RotationAxis = new Vector3(0, 1, 0);
现在请注意下面的 gif:
合成动画似乎在旋转,视角更偏右,而不是完全居中。我的投影矩阵需要改变吗?
快速回答。
yourVisual.Offset = new Vector3((float)Window.Current.Bounds.Width / 2, (float)Window.Current.Bounds.Height / 2, 0);
这样就可以了。应用了变换矩阵的移位视觉对象。 没有它,你的视角中心是左上角。
终于得到修复,如前所述 here,只需用容器包装受影响的控件即可解决问题:
所以在我的 Xaml 我有:
<Border Width="300"
Height="250"
Background="LightSeaGreen"
x:Name="Persp"
Margin="0,0,0,40">
<TextBlock Text="Composition"
FontSize="28"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Foreground="White" />
</Border>
我改成了:
<Border Width="300"
Height="250">
<Border Background="LightSeaGreen"
x:Name="Persp"
Margin="0,0,0,40">
<TextBlock Text="Composition"
FontSize="28"
HorizontalAlignment="Center"
VerticalAlignment="Center"
FontWeight="Bold"
Foreground="White" />
</Border>
</Border>