Render 3ds 3D-models with WPF and XAML
Section: WPFRating: Not rated yet!

Add to YiGGAdd to google-bookmarksAdd to linkarenaAdd to redditAdd to del.icio.usAdd to misterwongAdd to digg


zip-attachment Attachment




Introduction

In this article the author describes how to display 3D-models with WPF. The model in the example is converted from 3ds to XAML and rendered in a WPF application. The model can also be moved around with the mouse by using WPF transformations.


Figure 1

The concept


Displaying 3D graphics in WPF is easy: You have to define a ViewPort3D-object, a camera, at least one light and of course the models you want to display. In our past articles about WPF and 3D graphics we defined the vertices for the 3d models ourselves cause the rendered models were primitive ones. In this article a complex 3d model will be rendered, that has been designed with 3D Studio Max (3ds-file). To achieve this, we will have to export a 3ds-model to XAML. There are some nice tools available to convert 3ds to XAML, we will use a free one called Viewer3DS from Andrej Benedik available here. You can just drag and drop a 3s file to Viewer3ds and export the whole model to XAML.
The model we display in our example is a free model which we downloaded here.

The Project


The project is a normal WPF application created with VS 2008 Beta2. The project contains a main WPF-window with an empty Grid-definition. To display the 3D-model we copy and paste the exported XAML to the GRID-tag (here is just the beginning, the full project is attached as zip):

<Window x:Class="Wpf3DModel.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="3ds-model with WPF and XAML" Height="480" Width="640" WindowStartupLocation="CenterScreen"> <Grid> <Viewport3D x:Name="viewport" ClipToBounds="True"> <Viewport3D.Resources> <MeshGeometry3D x:Key="mesh_0" .. .. .. </Window>

That's all to display our 3D model. But we are not satisfied, right? Let's add some mouse interaction.

Transformations


To be able to move the model around with the mouse, we need to interact with the camera-object. We give the Perspective-camera a name and then it is available in our C#-codebehind:

<PerspectiveCamera x:Name="camera" Position="341.1015894,-20.5287564,78.6265847" LookDirection="41.6585119261428,24.0515530745978,-12.8891884461055" UpDirection="0,0,1" NearPlaneDistance="5" FarPlaneDistance="500" FieldOfView="60" />

For the mouse-interaction we define a little helper-class:

public class MouseHelper { private FrameworkElement _eventSource; private Point _position; private Transform3DGroup _transform; private TranslateTransform3D _translate = new TranslateTransform3D(); public MouseHelper() { _transform = new Transform3DGroup(); _transform.Children.Add(_translate); } public Transform3D Transform { get { return _transform; } } public FrameworkElement EventSource { get { return _eventSource; } set { if (_eventSource != null) { _eventSource.MouseDown -= this.OnMouseDown; _eventSource.MouseUp -= this.OnMouseUp; _eventSource.MouseMove -= this.OnMouseMove; } _eventSource = value; _eventSource.MouseDown += this.OnMouseDown; _eventSource.MouseUp += this.OnMouseUp; _eventSource.MouseMove += this.OnMouseMove; } } private void OnMouseDown(object sender, MouseEventArgs e) { Mouse.Capture(EventSource, CaptureMode.Element); _position = e.GetPosition(EventSource); } private void OnMouseUp(object sender, MouseEventArgs e) { Mouse.Capture(EventSource, CaptureMode.None); } private void OnMouseMove(object sender, MouseEventArgs e) { Point currentPosition = e.GetPosition(EventSource); if (e.LeftButton == MouseButtonState.Pressed) { _translate.OffsetZ -= (_position.Y - currentPosition.Y) * 0.2; _translate.OffsetY -= (_position.X - currentPosition.X) * 0.2; } else if (e.RightButton == MouseButtonState.Pressed) { _translate.OffsetX += (_position.X - currentPosition.X); } _position = currentPosition; } }

The key-element for moving the model around is the TranslateTransform3D-object. When pressing the mouse, we remember the position of the cursor. To translate the model from one position to another we get the new point of the cursor in the event OnMouseMove and calculate the offet to the old point. This offset is assigned to the TranslateTransform3D-object. When pressing the left mouse-button the object is moved along the Z-axis and Y-axis, when pressing the right mouse-button it is moved along the X-axis.

And here is how to use it in the MainWindow-class (viewport is the name of the ViewPort3D-object we defined):

public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); MouseHelper tb = new MouseHelper(); tb.EventSource = viewport; camera.Transform = tb.Transform; } }

Just a moment


When moving the model along the X-axis it is moving backward and forward? Why? Have a look at the UpDirection-property of the camera. The vector is (0,0,1). The camera is turned around. Did you get it? Think about it.

The project for VS 2008 Beta2 is attached? have fun




 Reader-Comments: