65.9K
CodeProject 正在变化。 阅读更多。
Home

音乐视频盒 (WPF)

starIconstarIconstarIconstarIconemptyStarIcon

4.00/5 (4投票s)

2009年8月8日

CPOL

3分钟阅读

viewsIcon

40234

downloadIcon

1830

本文解释了如何使用 Windows Presentation Foundation 3D 几何和媒体类创建音乐视频盒,以播放用户选择的音乐专辑。

引言

本文解释了如何使用 Windows Presentation Foundation 3D 几何和媒体类创建音乐视频盒,以播放用户选择的音乐专辑。

引言

这款音乐视频盒的设计方式是存储了三张不同专辑的音乐曲目,用户可以选择一张专辑和他们想播放的曲目。 专辑列表显示在左侧面板上,每张专辑的曲目以图片形式显示在 3D 立方体的侧面,该立方体旋转,方便用户选择他们喜欢的曲目。

最初,屏幕看起来像这样

该应用程序的中心是 3D 立方体,它显示当前专辑的曲目图片,并以顺时针方向旋转。

选择一张专辑(例如:印度灵修音乐)后,立方体呈现不同的外观,带有代表专辑中曲目的图片,如下所示

点击图片后,会打开另一个窗口,为您播放相应的视频,如下所示

WPF – 3D 几何和材质

立方体的侧面是使用 MeshGeometry3D 类单独创建的,该类构建 3D 形状。 它允许我们指定位置、法线和纹理坐标信息。

<MeshGeometry3D x:Key="CubeSide01" 
      TriangleIndices="0,1,2 3,4,5"
      Normals="-1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 -1,0,0 "
      TextureCoordinates="0,1 0,0 1,0 1,0 1,1 0,1 "
      Positions="-0.5,0.5,-0.5 -0.5,-0.5,-0.5 -0.5,-0.5,0.5 -0.5,
                 -0.5,0.5 -0.5,0.5,0.5 -0.5,0.5,-0.5 " />

立方体的侧面由 Material 组成,在本例中为 DiffuseMaterial,它允许应用程序应用 2D 画笔,例如 SolidColorBrushTileBrush,用于漫反射光照的 3D 模型。 对于列表中选择的专辑,此 Material 被动态地应用于侧面,ImageBrush 用于包含视频曲目的专辑(灵修和 Taare Zameen Par),LinearGradientBrush 用于未选择或只有一首视频的专辑(流行/摇滚)。

<MaterialGroup x:Key="TaareMaterial1">
    <DiffuseMaterial>
          <DiffuseMaterial.Brush>
                <ImageBrush Stretch="Fill" 
                     ImageSource="images\Taare\Taare1.jpg" 
                     TileMode="None" ViewportUnits="Absolute" 
                     Viewport="0 0 1 1" AlignmentX="Left" 
                     AlignmentY="Top" Opacity="1.000000" />
          </DiffuseMaterial.Brush>
    </DiffuseMaterial>
</MaterialGroup>

几何和材质的细节都在 app.xaml 中编码为应用程序资源。

用于 3D 图形的 XAML

<Viewport3D  MouseDown="myViewport_MouseDown" 
           ClipToBounds="True" Width="600" 
           Height="400" Name="myViewport" Focusable="True" >
      <Viewport3D.Camera>
           <PerspectiveCamera x:Name="myPerspectiveCamera"
              FarPlaneDistance="15" LookDirection="0,0,1" 
              UpDirection="0,1,0" NearPlaneDistance="1" 
              Position="0,0,-3" FieldOfView="50" />
      </Viewport3D.Camera>
      <ModelVisual3D x:Name="topModelVisual3D">
            <ModelVisual3D.Children>
               <ModelVisual3D>
                     <ModelVisual3D.Content>
                         ...............
                         ...............
      <ModelVisual3D x:Name="side1ModelVisual">
            <ModelVisual3D.Content>
                   <GeometryModel3D x:Name="side1GeometryModel3D" 
                       Geometry="{StaticResource CubeSide01}" 
                       Material="{StaticResource InitMaterial1}" 
                       BackMaterial="{StaticResource InsideMaterial}"/>
            </ModelVisual3D.Content>
      </ModelVisual3D>

HitTest

HitTest 是用户点击 3D 立方体侧面时采取的操作。 这在 ChooseTrack 方法中实现,其中鼠标位置参数从 MouseButtonEventArgs 中检索,我们在 ViewPort3D 中测试结果。

public void ChooseTrack(object sender, System.Windows.Input.MouseButtonEventArgs args)
{
    if (listboxAlbum.SelectedIndex <= 0)
        return;
    Point mouseposition = args.GetPosition(myViewport);
    PointHitTestParameters pointparams = new PointHitTestParameters(mouseposition);

   //test for a result in the Viewport3D
   VisualTreeHelper.HitTest(myViewport, null, HTResult, pointparams);
}

HitTest 方法将 ViewPort 对象作为参数以及回调方法 HTResult 和位置参数。 在回调方法 HTResult 中,我们使用 RayMeshGeometry3DHitTestResult 对象并调用 ModelHit 以获取用户点击鼠标的三维形状的 GeometryModel3D 对象。

public HitTestResultBehavior HTResult(System.Windows.Media.HitTestResult rawresult)
{
      RayHitTestResult rayResult = rawresult as RayHitTestResult;
      if (rayResult != null)
      {
          RayMeshGeometry3DHitTestResult rayMeshResult = 
                       rayResult as RayMeshGeometry3DHitTestResult;
          if (rayMeshResult != null)
          {
              GeometryModel3D hitgeo = rayMeshResult.ModelHit as GeometryModel3D;
              SetTrack(hitgeo);
              PlayTrack();
          }
      }

      return HitTestResultBehavior.Stop;
}

有两个辅助方法,SetTrack 用于选择曲目,PlayTrack 用于在窗口中打开 MediaElement 以播放视频。 在 SetTrack 方法中,创建一个 MusicPlayer 实例,并通过调用 FindAlbumFindTrack 方法分别设置属性 CurrentAlbumCurrentTrackPath

public void SetTrack(GeometryModel3D hitgeo)
{
  mplayer = new MusicPlayer();
  mplayer.currentAlbum = AvailTracks.FindAlbum(listboxAlbum.SelectedIndex - 1);
  // For pop/rock, only one video is placed. On clicking any picture
  // on any of the 6 sides, the same video plays.
  if (listboxAlbum.SelectedIndex == 2)
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 0);
    return;
  }
  if (hitgeo.Geometry==MeshGeometry3D)Application.Current.Resources["CubeSide01"])
  {
     mplayer.currtrapath =AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 0);
  }
  else if (hitgeo.Geometry==(MeshGeometry3D)Application.Current.Resources["CubeSide02"])
  {
    mplayer.currtrapath =AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 1);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide03"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 2);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide04"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 3);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide05"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 4);
  }
  else if (hitgeo.Geometry == (MeshGeometry3D)Application.Current.Resources["CubeSide06"])
  {
    mplayer.currtrapath = AvailTracks.FindTrack(listboxAlbum.SelectedIndex - 1, 5);
  }
}

PlayTrack 方法中,MusicPlayer 显示为一个对话框,如下所示

public void PlayTrack()
{
    mplayer.ShowDialog();
}

选择专辑后,立方体侧面的图片会发生变化,SetMaterial 方法用于此目的。 例如,如下调用此方法

setSideMaterial("TaareMaterial");

将为立方体的每一侧应用在 App.xaml 中定义的相应材质资源。

public void setSideMaterial(string materialKey)
{
    side1GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"1"];
    side2GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"2"];
    side3GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"3"];
    side4GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"4"];
    side5GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"5"];
    side6GeometryModel3D.Material = 
      (MaterialGroup) Application.Current.Resources[materialKey+"6"];
}

音乐视频盒的 Album 类

随此应用程序提供的音乐视频存储在应用程序文件夹内的子文件夹中。 视频文件的名称被检索并存储在 AlbumCollection 类的实例中。 AlbumCollection 类是一个泛型类,类型为 Album,包含两个属性,即 AlbumNameTrackPath,以及一个字符串数组。

public static class AlbumList
{
    public static AlbumCollection CreateAlbums()
    {
        string[] Devotelist = System.IO.Directory.GetFiles(@"e:\bala\music " + 
                              @"video box\tracks\devotional", "*.wmv");
        string[] PopRocklist = System.IO.Directory.GetFiles(@"e:\bala\music " + 
                               @"video box\tracks\poprock", "*.wmv");
        string[] Taarelist = System.IO.Directory.GetFiles(
                             @"e:\bala\music video box\tracks\taaree", "*.wmv");
        AlbumCollection ac = new AlbumCollection();
        ac.Add(new Album("Devotional", Devotelist));
        ac.Add(new Album("Pop/Rock", PopRocklist));
        ac.Add(new Album("Taare Zameen Par", Taarelist));
        return ac;
    }

结论

这个带有三张专辑的音乐视频盒是使用 WPF 的 3D 技术创建的。

© . All rights reserved.