Introduction
This article explains the creation of a Music Video Box using the Windows Presentation Foundation 3D Geometry and Media classes to play music albums as chosen by the user.
Introduction
This Music Video Box is designed in a way that it stores music tracks of three different albums and the user can select an album and the track he wants to play. While the list of albums appears on the left side panel, the tracks for each album are represented as pictures on the sides of a 3D cube that rotates for easier selection of the track the user prefers.
Initially, the screen looks like this:
The epicenter of this application is the 3D cube that displays pictures of the tracks of the current album, and it rotates in clockwise direction.
Upon selection of an album (e.g.: Hindu Devotional), the cube takes a different look with pictures representing the tracks in the album, as below:
Upon clicking the picture, another window opens up that plays the corresponding video for you, as below:
WPF – 3D Geometry and Material
The sides of the cubes are created separately using the MeshGeometry3D
class that builds a 3D shape. It allows us to specify the position, normal, and texture coordinate information.
<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 " />
The sides of the cube compose of a Material
, DiffuseMaterial
in this case, that allows the application of a 2-D brush, like a SolidColorBrush
or TileBrush
, for a diffusely-lit 3-D model. For the album selected in the list, this Material
is applied on the sides dynamically, ImageBrush
for the albums (Devotional and Taare Zameen Par) that contain the video tracks, and LinearGradientBrush
for no selection or an album (Pop/Rock) that has only one video.
<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>
Both the Geometry and Material specifics are coded as Application Resources in app.xaml.
XAML for 3D Graphics
<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
The HitTest is the action that is taken when the user clicks on a side of the 3D cube. This is implemented in the ChooseTrack
method wherein the mouse position parameters are retrieved from the MouseButtonEventArgs
and we test for a result in the 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);
VisualTreeHelper.HitTest(myViewport, null, HTResult, pointparams);
}
The HitTest method takes the ViewPort
object as a parameter along with a callback method HTResult
and the position parameters. It is in the callback method HTResult
, we use the RayMeshGeometry3DHitTestResult
object and calls ModelHit
to get the GeometryModel3D
object for the three-dimensional shape where the user hits the mouse.
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;
}
There are two helper methods, SetTrack
to select the track and PlayTrack
to open the MediaElement
in a window to play the video. In the SetTrack
method, a MusicPlayer
instance is created, and the properties CurrentAlbum
and CurrentTrackPath
are set by calling the FindAlbum
and FindTrack
methods, respectively.
public void SetTrack(GeometryModel3D hitgeo)
{
mplayer = new MusicPlayer();
mplayer.currentAlbum = AvailTracks.FindAlbum(listboxAlbum.SelectedIndex - 1);
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);
}
}
In the PlayTrack
method, the MusicPlayer
is shown as a dialog as coded below:
public void PlayTrack()
{
mplayer.ShowDialog();
}
On selecting an album, the pictures of the sides of the cube changes, and the method SetMaterial
is used for this purpose. For example, calling this method as below:
setSideMaterial("TaareMaterial");
would apply the corresponding material resource defined in App.xaml for each side of the cube.
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"];
}
Music Video Box’s Album class
The music videos supplied along with this application are stored in a sub-folder inside the application folder. The names of the video files are retrieved and are stored in the instances of the AlbumCollection
class. The AlbumCollection
class is a generic class of type Album
that contains two properties namely AlbumName
and TrackPath
, and an array of strings.
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;
}
Conclusion
This Music Video Box with three albums is created using WPF’s 3D technologies.