65.9K
CodeProject is changing. Read more.
Home

All New .NET 3.5 3D Elements

starIconstarIconstarIconstarIconstarIcon

5.00/5 (3 votes)

Jun 17, 2009

CPOL
viewsIcon

16811

downloadIcon

153

All new .NET 3.5 3D elements

I have started looking at 3D again in WPF. I have in the past blogged about the Viewport2DVisual3D 3D WPF element. Well for what I am working on, I didn’t need to be able to put 2D interactive elements on a 3D surface, but I did want the 3D object to able to respond to Mouse events.  Now in the past, what you would have done is use a MouseDown event on the Viewport3D and do some sort of hit testing. Which was ok….

But now, there is the wonderful new .NET 3.5 element ModelUIElement3D which is a fully fledged element that supports events. Hooray!

And there is also a new container element to host 1 or more ModelUIElement3D elements.

Let's see an example:

<Window x:Class=”Shapes.Window1″
    xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
    xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
    xmlns:local=”clr-namespace:Shapes”
    Title=”Window1″ Height=”610.122″ Width=”633.46″>

    <Window.Resources>

        <!– The 3D cube –>
        <MeshGeometry3D x:Key=”CubeMesh”
            TriangleIndices = “0,1,2     2,3,0
                               4,7,6     6,5,4
                               8,11,10   10,9,8
                               12,13,14  14,15,12
                               16,17,18  18,19,16
                               20,23,22  22,21,20″

             Positions      = “-1,-1,1   -1,-1,-1  1,-1,-1  1,-1,1
                               -1,1,1    -1,1,-1   1,1,-1   1,1,1
                               -1,-1,1   -1,1,1    1,1,1    1,-1,1
                               -1,-1,-1  -1,1,-1   1,1,-1   1,-1,-1
                               -1,-1,1   -1,1,1   -1,1,-1  -1,-1,-1
                                1,-1,1    1,1,1    1,1,-1   1,-1,-1″ />
    </Window.Resources>

    <Viewport3D>

        <Viewport3D.Camera>
            <PerspectiveCamera x:Name=”camera” Position=”-2,2,5″
                               LookDirection=”2,-2,-5″ FieldOfView=”90″ />
        </Viewport3D.Camera>

        <!– Container for 3D Elements –>
        <ContainerUIElement3D x:Name=”container”>
            <ContainerUIElement3D.Transform>
                <RotateTransform3D>
                    <RotateTransform3D.Rotation>
                        <AxisAngleRotation3D Axis=”0, 1, 0″ Angle=”0″ />
                    </RotateTransform3D.Rotation>
                </RotateTransform3D>
            </ContainerUIElement3D.Transform>

            <!– A fully Fledged 3d element complete with routed events –>
            <ModelUIElement3D MouseDown=”Cube1_MouseDown”>
                <ModelUIElement3D.Transform>
                    <Transform3DGroup>
                        <TranslateTransform3D OffsetZ=”1.5″ />
                        <RotateTransform3D>
                            <RotateTransform3D.Rotation>
                                <AxisAngleRotation3D Axis=”0, 1, 0″ Angle=”0″ />
                            </RotateTransform3D.Rotation>
                        </RotateTransform3D>
                    </Transform3DGroup>
                </ModelUIElement3D.Transform>
                <ModelUIElement3D.Model>
                    <GeometryModel3D Geometry=”{StaticResource CubeMesh}”>
                        <GeometryModel3D.Material>
                            <DiffuseMaterial x:Name=”cube1Material” Brush=”Blue” />
                        </GeometryModel3D.Material>
                    </GeometryModel3D>
                </ModelUIElement3D.Model>
            </ModelUIElement3D>
        </ContainerUIElement3D>

        <ModelVisual3D>
            <ModelVisual3D.Content>
                <DirectionalLight Color=”White” Direction=”-1,-1,-1″/>
            </ModelVisual3D.Content>
        </ModelVisual3D>

    </Viewport3D>

</Window>

And here is the C# code that has the event for the ModelUIElement3D.

   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Windows;
   6:  using System.Windows.Controls;
   7:  using System.Windows.Data;
   8:  using System.Windows.Documents;
   9:  using System.Windows.Input;
  10:  using System.Windows.Media;
  11:  using System.Windows.Media.Animation;
  12:  using System.Windows.Media.Media3D;
  13:  using System.Windows.Media.Imaging;
  14:  using System.Windows.Navigation;
  15:  using System.Windows.Shapes;
  16:  
  17:  namespace Shapes
  18:  {
  19:      /// <summary>
  20:      /// Interaction logic for Window1.xaml
  21:      /// </summary>
  22:      public partial class Window1 : Window
  23:      {
  24:  
  25:  
  26:          public Window1()
  27:          {
  28:              InitializeComponent();
  29:          }
  30:  
  31:  
  32:          /// <summary>
  33:          /// 3d Element Mouse Event, Neat
  34:          /// </summary>
  35:          private void Cube1_MouseDown(object sender, MouseButtonEventArgs e)
  36:          {
  37:              ModelUIElement3D currentObject = sender as ModelUIElement3D;
  38:              if (currentObject.Transform is Transform3DGroup)
  39:              {
  40:                  RotateTransform3D rotateTrans = null;
  41:  
  42:                  Transform3DGroup transGroup =
  43:                      currentObject.Transform as Transform3DGroup;
  44:                  rotateTrans = TryFindChild<RotateTransform3D>(transGroup);
  45:                  if (rotateTrans != null)
  46:                  {
  47:                      // spin the object around
  48:                      DoubleAnimation doubleAnimation =
  49:                          new DoubleAnimation(0,360,
  50:                          new Duration(TimeSpan.FromSeconds(0.5)));
  51:                      rotateTrans.Rotation.BeginAnimation(
  52:                          AxisAngleRotation3D.AngleProperty, doubleAnimation);
  53:                  }
  54:              }
  55:          }
  56:  
  57:  
  58:          /// <summary>
  59:          /// Try and find child of type T in the Transform3DGroup
  60:          /// </summary>
  61:          public static T TryFindChild<T>(Transform3DGroup parent)
  62:            where T : DependencyObject
  63:          {
  64:              foreach (DependencyObject child in parent.Children)
  65:              {
  66:                  if (child is T)
  67:                  {
  68:                      return child as T;
  69:                  }
  70:              }
  71:              return null;
  72:          }
  73:  
  74:  
  75:      }
  76:  }

And that is all there is to it. So in this example, if the cube gets a MouseDown, I lookup its RotateTransform3D and spin it around by 360 degrees.

37354/image-thumb6.png

And here is a zip file with the demo project code.