1

我正忙于将 WPF 解决方案迁移到 Windows 应用商店应用程序。该解决方案使用ViewPort3D您在应用程序开发中没有,因此我尝试使用PlaneProjection.

目标是实现一个可以用故事板围绕一个轴旋转的立方体。我对立方体的侧面没有任何问题,但顶部的矩形让我头疼。

我制作了一个测试集来可视化我的问题。如果您创建一个新的 blanc Windows 应用商店应用程序(不是电话)并将其命名,PlaneTest然后将 XAML 粘贴到您的整个应用程序MainPage.xaml中,并将 C# 类放在MainPage.xaml.cs.

XAML:

<Page
    x:Class="PlaneTest.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:PlaneTest"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="500"/>
            <ColumnDefinition Width="700"/>
        </Grid.ColumnDefinitions>   
        <Grid.Resources>
            <Style TargetType="Slider">
                <Setter Property="Width" Value="400"/>
                <Setter Property="Height" Value="23"/>
            </Style>
            <Style TargetType="TextBlock">
                <Setter Property="Margin" Value="0,5,0,0"/>
            </Style>
        </Grid.Resources>
        <StackPanel Orientation="Vertical" Width="450" Grid.Column="0">
            <TextBlock Text="CUBE SLIDERS" Margin="25"></TextBlock>
            <TextBlock Text="Rotation X = 23. CUBE ROTATES AROUND THIS AXIS."></TextBlock>
            <Slider Name="RotateX" Minimum="-90" Maximum="90" Value="23"></Slider>
            <TextBlock Text="Rotation Y = -25"></TextBlock>
            <Slider Name="RotateY" Minimum="-90" Maximum="90" Value="-25"></Slider>
            <TextBlock Text="Rotation Z = -90"></TextBlock>
            <Slider Name="RotateZ" Minimum="-90" Maximum="90" Value="-90"></Slider>

            <TextBlock Text="TOP RECTANGLE" Margin="25,50,0,0"></TextBlock>
            <TextBlock Text="Rotation X"></TextBlock>
            <Slider Name="TopRotateX" Minimum="-180" Maximum="180"></Slider>
            <TextBlock Text="Rotation Y"></TextBlock>
            <Slider Name="TopRotateY" Minimum="-180" Maximum="180"></Slider>
            <TextBlock Text="Rotation Z"></TextBlock>
            <Slider Name="TopRotateZ" Minimum="-180" Maximum="180"></Slider>

            <TextBlock Text="Center Of Rotation X" Margin="0,40,0,0"></TextBlock>
            <Slider Name="CenterOfXRotation" Value="0.5" Minimum="0" Maximum="1" StepFrequency="0.1"></Slider>
            <TextBlock Text="Center Of Rotation Y"></TextBlock>
            <Slider Name="CenterOfYRotation" Value="0.5" Minimum="0" Maximum="1" StepFrequency="0.1"></Slider>
            <TextBlock Text="Center Of Rotation Z"></TextBlock>
            <Slider Name="CenterOfZRotation" Value="200" Minimum="-200" Maximum="200"></Slider>

            <TextBlock Text="GlobalOffSet X" Margin="0,40,0,0"></TextBlock>
            <Slider Name="GlobalXOffSet"  Minimum="-200" Maximum="200" ></Slider>
            <TextBlock Text="GlobalOffSet Y"></TextBlock>
            <Slider Name="GlobalYOffSet" Width="400" Height="23" Minimum="-200" Maximum="200"></Slider>
            <TextBlock Text="GlobalOffSet Z"></TextBlock>
            <Slider Name="GlobalZOffSet" Minimum="-200" Maximum="200"></Slider>
         </StackPanel>     

        <Grid x:Name="LayoutRoot"  Grid.Column="1">
            <Grid.Resources>
                <Style TargetType="Rectangle">
                    <Setter Property="Height" Value="400"/>
                    <Setter Property="Width" Value="400"/>
                </Style>
                <local:RotationXOffset x:Key="rotationXOffset"/>
            </Grid.Resources>

            <Rectangle Fill="#a0FF0000" Name="Side1">
               <Rectangle.Projection>
                   <PlaneProjection CenterOfRotationZ="200" 
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ,Path=Value}"/>
                    </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a00000FF" Name="Side2">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-0'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a0EFFF30" Name="Side3">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"                          
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#af00FF00" Name="Side4">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='180'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="Orange"  Name="Top">
                <Rectangle.Projection>
                    <PlaneProjection
                               CenterOfRotationX="{Binding ElementName=CenterOfXRotation, Path=Value}"
                               CenterOfRotationY="{Binding ElementName=CenterOfYRotation, Path=Value}"
                               CenterOfRotationZ="{Binding ElementName=CenterOfZRotation, Path=Value}"
                               GlobalOffsetX="{Binding ElementName=GlobalXOffSet, Path=Value}"
                               GlobalOffsetY="{Binding ElementName=GlobalYOffSet, Path=Value}"
                               GlobalOffsetZ="{Binding ElementName=GlobalZOffSet, Path=Value}"
                               RotationX="{Binding ElementName=TopRotateX, Path=Value}" 
                               RotationY="{Binding ElementName=TopRotateY, Path=Value}" 
                               RotationZ="{Binding ElementName=TopRotateZ, Path=Value}" />
                </Rectangle.Projection>
            </Rectangle>
        </Grid>  
    </Grid>
</Page>

C#

 class RotationXOffset : IValueConverter
    {
        object IValueConverter.Convert(object value, Type targetType, object parameter, string language)
        {
            return (double)value + Convert.ToDouble(parameter);
        }

        object IValueConverter.ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }

如果您不触摸 3 个顶部滑块,请尝试使用其他滑块将橙色顶部矩形放在立方体顶部。我不能。

当我将 Rotation X most top 滑块移动到 0 或 90 时,我可以拟合顶部,但不能使用任何其他值。我究竟做错了什么?甚至有可能PlaneProjection吗?我是否遇到了这种仿射变换限制? http://www.charlespetzold.com/blog/2009/01/Non-Affine-Transforms-in-Silverlight.html

4

1 回答 1

0

与此同时,我正在研究另一个项目,现在回到这个解决方案,我重新审视了它。

使用这个 XAML 和问题中的值转换器,它可以按我的意愿工作。

<Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="500"/>
            <ColumnDefinition Width="700"/>
        </Grid.ColumnDefinitions>   
        <Grid.Resources>
            <Style TargetType="Slider">
                <Setter Property="Width" Value="400"/>
                <Setter Property="Height" Value="23"/>
            </Style>
            <Style TargetType="TextBlock">
                <Setter Property="Margin" Value="0,5,0,0"/>
            </Style>
        </Grid.Resources>
        <StackPanel Orientation="Vertical" Width="450" Grid.Column="0">
            <TextBlock Text="CUBE SLIDERS" Margin="25"></TextBlock>
            <TextBlock Text="Rotation X = 23. CUBE ROTATES AROUND THIS AXIS."></TextBlock>
            <Slider Name="RotateX" Minimum="-90" Maximum="90" Value="23"></Slider>
            <TextBlock Text="Rotation Y = -25"></TextBlock>
            <Slider Name="RotateY" Minimum="-90" Maximum="90" Value="-25"></Slider>
            <TextBlock Text="Rotation Z = -90"></TextBlock>
            <Slider Name="RotateZ" Minimum="-90" Maximum="90" Value="-90"></Slider>
        </StackPanel>     

        <Grid x:Name="LayoutRoot"  Grid.Column="1">
            <Grid.Resources>
                <Style TargetType="Rectangle">
                    <Setter Property="Height" Value="400"/>
                    <Setter Property="Width" Value="400"/>
                </Style>
                <local:RotationXOffset x:Key="rotationXOffset"/>
            </Grid.Resources>

            <Rectangle Fill="#a0FF0000" Name="Side1">
               <Rectangle.Projection>
                   <PlaneProjection CenterOfRotationZ="200" 
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ,Path=Value}"/>
                    </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a00000FF" Name="Side2">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='-0'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#a0EFFF30" Name="Side3">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"                          
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='90'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

            <Rectangle Fill="#af00FF00" Name="Side4">
                <Rectangle.Projection>
                    <PlaneProjection CenterOfRotationZ="200"
                                RotationX="{Binding ElementName=RotateX, Path=Value, Converter={StaticResource rotationXOffset}, ConverterParameter='180'}" 
                                RotationY="{Binding ElementName=RotateY, Path=Value}"
                                RotationZ="{Binding ElementName=RotateZ, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>

        </Grid>  
        <Grid Grid.Column="1">
            <Grid.Projection>
                <PlaneProjection RotationX="115" CenterOfRotationZ="200"/>
            </Grid.Projection>
            <Rectangle Fill="Orange"  Name="Top" Height="400" Width="400" >
                <Rectangle.Projection>
                    <PlaneProjection RotationZ="{Binding ElementName=RotateX, Path=Value}"/>
                </Rectangle.Projection>
            </Rectangle>
        </Grid>
    </Grid>
于 2014-11-18T17:25:15.403 回答