好玩的WPF第四彈:用Viewport2DVisual3D實現3D旋轉效果

nomasp發表於2015-06-20

這裡寫圖片描述

效果呢就是這麼個效果,但是大家要發揮想象力,比如做成一個可以旋轉的按鈕等等。

定義一個這樣的資源就好。

<Window.Resources>
        <DiffuseMaterial x:Key="DiffuseMaterialStyle" Viewport2DVisual3D.IsVisualHostMaterial="True" 
                         Brush="White"/>
</Window.Resources>

關鍵是在Grid裡放這麼一個東西:

 <Viewport3D x:Name="view" ClipToBounds="True" RenderOptions.EdgeMode="Aliased">                
     <Viewport3D.Camera>
          <PerspectiveCamera x:Name="perspectiveCam" FieldOfView="59" Position="0.5,0.5,2" LookDirection="0,0,-1">
              <PerspectiveCamera.Transform>
                   <RotateTransform3D x:Name="rot" CenterY="0.5" CenterX="0.5" CenterZ="-0.5">
                        <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D x:Name="AxisAngleRot" Axis="0,1,0" Angle="0"/>
                        </RotateTransform3D.Rotation>
                   </RotateTransform3D>
               </PerspectiveCamera.Transform>
           </PerspectiveCamera>
      </Viewport3D.Camera>                      
      <ModelVisual3D>
          <ModelVisual3D.Content>
               <AmbientLight Color="White" />
          </ModelVisual3D.Content>
      </ModelVisual3D>
</Viewport3D>

正面:

<Viewport2DVisual3D Material="{StaticResource  DiffuseMaterialStyle }">
    <Viewport2DVisual3D.Geometry>
         <MeshGeometry3D Positions="0,1,0    0,0,0     1,0,0    1,1,0"
              TextureCoordinates="0,0   0,1     1,1     1,0"
              TriangleIndices="0 1 2  0 2 3"/>
    </Viewport2DVisual3D.Geometry>
    <Border BorderThickness="10" x:Name="FrontSide" BorderBrush="Blue" CornerRadius="1"  
        PreviewMouseDown="FrontSide_PreviewMouseDown" >
        <TextBlock Text="歡迎訪問我的部落格" Foreground="Green" />
   </Border>
</Viewport2DVisual3D>

右側:

<Viewport2DVisual3D Material="{StaticResource DiffuseMaterialStyle}">
      <Viewport2DVisual3D.Geometry>
            <MeshGeometry3D Positions="1,1,0     1,0,0     1,0,-1     1,1,-1"
                TextureCoordinates="0,0 0,1 1,1 1,0"
                TriangleIndices="0 1 2  0 2 3"/>
       </Viewport2DVisual3D.Geometry>
       <Border BorderThickness="1" x:Name="RightSide" BorderBrush="Lime" CornerRadius="4"
           PreviewMouseDown="RightSide_PreviewMouseDown"  >
           <Border.Background>
                <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                    <GradientStop Color="White" />
                </LinearGradientBrush>
            </Border.Background>
            <TextBlock Text="感謝您的支援" FontSize="20"/>
       </Border>
</Viewport2DVisual3D>

大家對比上面這兩個就知道正面的鏤空是怎麼來的了……

左側:

<Viewport2DVisual3D Material="{StaticResource DiffuseMaterialStyle}">
      <Viewport2DVisual3D.Geometry>
            <MeshGeometry3D Positions="0,1,-1    0,0,-1   0,0,0    0,1,0"   
            TextureCoordinates="0,0 0,1 1,1 1,0"
            TriangleIndices="0 1 3  0 2 3"/>
           </Viewport2DVisual3D.Geometry>
           <Border BorderThickness="40" x:Name="LeftSide" BorderBrush="White" CornerRadius="1" 
                  PreviewMouseDown="LeftSide_PreviewMouseDown" >
              <Border.Background>
                  <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                      <GradientStop Color="Black" />
                   </LinearGradientBrush>
               </Border.Background>
          <TextBlock Text="有問題直接評論就好" Foreground="Lime"/>
     </Border>
</Viewport2DVisual3D>

後方:

<Viewport2DVisual3D Material="{StaticResource DiffuseMaterialStyle}">
    <Viewport2DVisual3D.Geometry>
        <MeshGeometry3D Positions="1,1,-1    1,0,-1     0,0,-1     0,1,-1   0,0.5,-1"
           TextureCoordinates="0,0    0,1    1,1    1,0"
           TriangleIndices="0 1 2  0 2 4"/>
    </Viewport2DVisual3D.Geometry>
    <Border BorderThickness="1" x:Name="BackSide" BorderBrush="White" CornerRadius="4" 
         PreviewMouseDown="BackSide_PreviewMouseDown" >
        <Border.Background>
           <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
               <GradientStop Color="White" />
           </LinearGradientBrush>
        </Border.Background>
        <TextBlock Text="常來哦……" FontSize="20"/>
   </Border>
</Viewport2DVisual3D>

大家先不管MeshGeometry3D這些東西是做什麼的,後面我儘量簡單快速的講解它們。

所以先來看看程式的內部。

    public partial class MainWindow : Window
    {
        DispatcherTimer dispatTime = null;
        double AxAngle = 90;

        public MainWindow()
        {
            InitializeComponent();

            if (dispatTime == null)
                dispatTime = new DispatcherTimer();
            dispatTime.Tick += new EventHandler(DT_Tick);
            dispatTime.Interval = new TimeSpan(0, 0, 0, 0, 2);
        }                       


        private void DT_Tick(object sender, EventArgs e)
        {
            AxisAngleRot.Angle += 1;
            if (AxisAngleRot.Angle >= AxAngle)
                dispatTime.Stop();
        }

        private void FrontSide_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            AxisAngleRot.Angle = 0;
            AxAngle = 90;
            dispatTime.Start();
        }

        private void LeftSide_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            AxAngle = 360;
            dispatTime.Start();
        }

        private void BackSide_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            AxAngle = 270;
            dispatTime.Start();
        }


        private void RightSide_PreviewMouseDown(object sender, MouseButtonEventArgs e)
        {
            AxAngle = 180;
            dispatTime.Start();
        }
    }

像這種程式肯定會涉及到計時器的,就是DT_Tick方法。我將它設定為每次都轉動1度,而下面這一行則是間隔的時間。

dispatTime.Interval = new TimeSpan(0, 0, 0, 0, 2);

其餘的每個方法都用於調節角度,可以看到在正面時會將角度重置一次。

所以接下來看看Positions是什麼意思。

這裡寫圖片描述

原諒我把正方體畫歪了,圖中另外用箭頭指出了“正面”、“右側”等。

大家看看Positions中都是3個數字一組對吧,這就是一個點,我在圖中已經標識出來了。而TriangleIndices中也是3個數字一組,這3個數字指示了Positions中的組合索引(從0開始索引),然後3個數字組成三角形,如圖中箭頭所指向的。

而TextureCoordinates是WPF的3D紋理座標,這裡就不深究的,後面可以深入探討寫一篇部落格。

大家也可以拿原始碼回去慢慢弄著玩嘛……

所以這篇部落格就到此為止咯。掰掰……

相關文章