Unplugged Viz
High-performance scientific visualization isn't just for the workstation anymore
Getting Started with Unplugged Viz

The samples contained within the download reference the included Unplugged Viz DLLs and show the basic functionality.

This topic demonstrates how to add an Unplugged Viz to your Xamarin.Forms app using C#. For more detailed information, see the API documentation here.

Included Functionality

Unplugged Viz includes three controls: a ColorMappedImageView, a ColorMappedPlotView<T>, and an XYPlotView<T>. ColorMappedImageView and ColorMappedPlotView<T> are used to plot 3-dimensional data in 2D with a user-definable color map; XYPlotView<T> is used for plotting 2-dimensional data in either line or bar chart form, with a color map applied.

Initializing

Note: Unplugged Viz depends on the MonoGame Framework. You should add a reference to the relevant MonoGame.Framework package (available via NuGet) to your each platform-specific project in order to use it. To use the CameraControl object, a reference to MonoGame.Framework.Portable is required on your PCL project. This library is available via NuGet but is currently a prerelease version and cannot be installed in Xamarin Studio; you may need to download the package manually.

In order to ensure Unplugged Viz's custom renderers are registered by Xamarin Forms, add a reference to Durwella.Unplugged.Viz.iOS.dll include the following in the initialization code for your iOS project (for example, in AppDelegate.cs).

1 Durwella.Unplugged.Viz.iOS.UnpluggedRenderers.Init();

In your Android project, the call is analogous; however, you should pass in a reference to your MainActivity object.

1 Durwella.Unplugged.Viz.Droid.UnpluggedRenderers.Init(this);

It is recommended that you place this line immediately before the call LoadApplication(new App ());.

ColorMappedImageView and ColorMappedPlotView

Durwella.Unplugged.Viz.ColorMappedImageView inherits from Xamarin.Forms.View, and therefore can be used anywhere you would use a View. It can take data either as a 2-dimensional array of byte, int, or float, or as a Durwella.Unplugged.Viz.RawDataArray. ColorMappedImageView is intended for cases when the data is in the form of a raw 1-dimensional array of byte, int, or float; it is intended to allow the user to avoid conversion to a 2D array for improved performance.

Durwella.Unplugged.Viz.ColorMappedPlotView<T> inherits from ColorMappedImageView and is a generic class where T is the class of the data to be displayed; T may be byte, int, or float. For situations where the user data is already stored as a T[,], ColorMappedPlotView<T> allows the user to create a plot view in a type-safe manner.

The following code illustrates creating a simple ContentPage containing a ColorMappedPlotView<float> in C#.

1 using Durwella.Unplugged.Viz;
2 using Xamarin.Forms;
3 
4 namespace Example
5 {
6  public class MyPage : ContentPage
7  {
8  public MyPage()
9  {
10  Content = new ColorMappedPlotView<float>();
11  }
12  }
13 }

The same result can be obtained in XAML.

1 <?xml version="1.0" encoding="UTF-8"?>
2 <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
3  xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
4  xmlns:unplugged="clr-namespace:Durwella.Unplugged.Viz;assembly=Durwella.Unplugged.Viz"
5  x:Class="Examples.MyPage">
6  <ContentPage.Content>
7  <unplugged:ColorMappedPlotView x:TypeArguments="x:Single"></unplugged:ColorMappedPlotView>
8  </ContentPage.Content>
9 </ContentPage>

Full API documentation can be found here; however, a description of some important properties of ColorMappedPlotView<T> is given below.

  • Data: A T[,] array defining the data to be plotted.
  • ColorMapRange: A Durwella.Unplugged.Viz.RangeF defining the Data values corresponding to the minimum and maximum of the ColorMap.
  • ColorMap: A Xamarin.Forms.Color[] array defining the color map. The full color map is interpolated linearly between values in the array and mapped to the Data between the two extremes of the ColorMapRange.
  • DataRange: A UDurwella.Unplugged.Viz.RectangleF the defines the numerical scales of the X- and Y-axes of the plot.

All properties are exposed as BindingProperties; for example, a ColorMappedPlotView<float> might be defined in XAML as follows.

1 <unplugged:ColorMappedPlotView x:TypeArguments="x:Single"
2  Data="{Binding Data}" ColorMap="{Binding ColorMap}">
3 </unplugged:ColorMappedPlotView>

A simple example is illustrated below. In this example, a 100x100 int array is created which varies diagonally from 0 at (0,0) to 200 at (100,100). It is then plotted using a ROYGBIV color map.

1 using Durwella.Unplugged.Viz
2 using Xamarin.Forms;
3 
4 namespace Example
5 {
6  public class MyPage : ContentPage
7  {
8  public MyPage()
9  {
10  var imageData = new int[100,100];
11 
12  for (int i = 0; i < 100; i++)
13  {
14  for (int j = 0; j < 100; j++)
15  {
16  imageData[i, j] = i + j;
17  }
18  }
19 
20  Content = new ColorMappedPlotView<int>
21  {
22  ColorMapRange = new RangeF(0, 200),
23  Data = imageData,
24  ColorMap = new Color[] { Color.Red, Color.FromHex("#FFA500"), Color.Yellow, Color.Green,
25  Color.Blue, Color.FromHex("#4B0082"), Color.FromHex("#8F5E99") }
26  }
27  }
28  }
29 }

XYPlotView

Durwella.Unplugged.Viz.XYPlotView<T> is used to plot 2-dimensional data with a color map. There are two types of XYPlot<T>s:

  • Line graph: Values between supplied data points are interpolated, and the region beneath the resulting curve is filled in with the color map based on the function values.
  • Bar chart: The values are plotted directly as bars. The colors of the bars are obtained from the color map.

Use of XYPlotView<T> is very similar to the use of ColorMappedPlotView<T>; the differences will be discussed below.

  • Data: The Data array is a 1-dimensional T[] array instead of T[,] as in ColorMappedPlotView<T>.
  • DataRange: DataRange is a 1-dimensional UDurwella.Unplugged.Viz.RangeF instead of a 2-dimensional Durwella.Unplugged.Viz.RectangleF. It defines the numerical scale of the independent axis; the dependent axis is defined by the ColorMapRange.
  • IsHorizontal: By default, XYPlot<T>s are plotted vertically from the top to the bottom of the screen. IsHorizontal is a boolean property that switches to a horizontal plot when set to true.
  • IsBarChart: XYPlot<T>s are displayed as line graphs by default. IsBarChart can be set to true to switch to a bar chart display.

A simple example is illustrated below. In this example, a 21-element float[] corresponding to the normal distribution is plotted as a horizontal bar chart. The x-axis ranges from -10 to 10, and the y-axis is set by the ColorMapRange, which defaults to [0,1] for XYPlotView<float>.

1 using System;
2 using System.Linq;
3 using Durwella.Unplugged.Viz
4 using Xamarin.Forms;
5 
6 namespace Example
7 {
8  public class MyPage : ContentPage
9  {
10  public MyPage()
11  {
12  float[] data = Enumerable.Range(0, 21)
13  .Select(i => (float)Math.Exp(-Math.Pow((i - 10.0) / 5.0, 2)))
14  .ToArray();
15 
16  Content = new XYPlotView<float>
17  {
18  IsHorizontal = true,
19  IsBarChart = true,
20  Data = data,
21  DataRange = new RangeF(-10, 10)
22  };
23  }
24  }
25 }

TumbleView

Durwella.Unplugged.Viz.TumbleView is used to display 3-dimensional models.

The TumbleView class is quite simple; it contains just two properties. Detailed information about each property will follow.

CameraControl

Durwella.Unplugged.Viz.CameraControl allows the control of the relative positions and orientations of the camera and the view. Using the default implementation, the camera will always point at the origin (0,0,0) and use the positive y-direction as the up direction. This can be changed by overriding methods (see the documentation); however, use care – the center of rotation when the use interacts with the view will always be the origin, which can result in strange interaction dynamics.

Important properties and methods of CameraControl are as follows:

  1. Orientation: A Microsoft.Xna.Framework.Quaternion describing the orientation of the TumbleView.
  2. Roll: A Quaternion describing the orientation of the CameraControl. The rotation of the scene is calculated by multiplying Roll * Orientation.
  3. Translation: A Microsoft.Xna.Framework.Vector3 describing the position of the view.
  4. CameraPosition: A Vector3 describing the position of the camera.
  5. ZoomScale: A float describing the zoom level of the camera; default to 1.0f.
  6. CreateModelMatrix(), CreateViewProjectionMatrix(), and CreateModelViewProjectionMatrix(): virtual methods which may be overridden to alter camera behavior. Default implementations of these methods are given in the documentation.

Models

All models to be used with TumbleView must implement Durwella.Unplugged.Viz.IGeometry and have certain attributes applies.

Control of model properties is via attributes. Every model to be used must include the following:

  1. A DrawWithAttribute defining how model will be drawn using OpenGL.
  2. Either a single ShaderAttribute or one or more each of VertexShaderAttributes and FragmentShaderAttributes, which define the shaders to be used in displaying the model.

The set of properties that may be used in shaders is limited to the following. Each property is defined in an interface; the model must implement the specified interface to use the property in a shader. The requisite interface for each property is given in parentheses.

  1. Array Vertices (IGeometry)
  2. int[] Indices (IIndexedGeometry)
  3. Array TextureCoordinates (ITexturedgGeometry)
  4. Array TextureMap (ITextureMappedGeometry)
  5. object Image (IImageMappedGeometry)
  6. Array ColorMap, float ColorMapMinimum, float ColorMapMaximum (IColorMappedGeometry)
  7. float[] Translation (ITranslatableGeometry)
  8. float[,] Orientation (IRotatableGeometry)
  9. Array[] Color, (IColoredGeometry)
  10. float[,] Normals, float[] LightPosition (ILitGeometry)

All models automatically get access to a Rotation and a ModelViewProjection property, which are the result of the CreateRotationMatrix() and CreateModelViewProjectionMatrix() methods, respectivley, on the CameraControl associated with the TumbleView. Your shader must include these properties even if they are unused (see below). If you need additional properties, please contact us at unplugged@durwella.com.

The properties are tagged with attributes to indicate their role in the shader. The attributes are listed below; see the API documentation for more information.

  1. VertexAttributeAttribute
  2. VertexIndicesAttribute
  3. UniformAttribute
  4. TextureMapAttribute
  5. ColorMapAttribute

The component ships with base classes which may be useful as starting points for model definition: IndexedGeometryModel, IndexedGeometryTextureMappedModel, and IndexedGeometryTextureMappedLitModel.

Example

Consider definining a simple model for an oil wellbore. The wellbore will be modeled as a connected series of line segments with a specified color. A possible definition of the well model is as follows:

1 [DrawWith(PrimitiveType.LineStrip, BackFaces.NotCulled)]
2 [Shader("WellModel")]
3 public class WellModel : BindableObject, IColoredGeometry
4 {
5  [Uniform]
6  public Array Color { get { return new float[] { 1, 0, 0, 1 }; } }
7 
8  [VertexAttribute]
9  public Array Vertices
10  {
11  get {
12  return new float[,] {
13  { 0.85f, 1.2f, -0.1f },
14  { 0.85f, 1.1f, -0.1f },
15  { 0.84f, 1.0f, -0.1f },
16  { 0.83f, 0.7f, -0.12f },
17  { 0.80f, 0.5f, -0.15f }
18  };
19  }
20  }
21 }

(Note: The model inherits from Xamarin.Forms.BindableObject, despite the fact that no property changed notifications are raised, and IGeometry must implement INotifyPropertyChanged.)

  • This model has a DrawWithAttribute with the following properties: "line strip" primitives and no backface culling. (See the documentation.)
  • The model has a ShaderAttribute with a ShaderName of "WellModel". This means that in each platform-specific project should be found two shaders: the fragment shader "WellModel.fsh" and the vertex shader "WellModel.vsh".
  • The model has a VertexAttribute property Vertices and a Uniform property Color.

The two shaders are given below:

WellModel.vsh:

1 attribute vec3 Vertices;
2 uniform mat4 ModelViewProjection;
3 uniform mat3 Rotation;
4 
5 void main()
6 {
7  Rotation;
8  gl_Position = ModelViewProjection * vec4(Vertices, 1.0);
9 }

(Note the inclusion of Rotation despite the fact it is unused.)

WellModel.fsh:

1 uniform vec4 Color;
2 
3 void main()
4 {
5  gl_FragColor = Color;
6 }

For more examples see the API documentation, the included sample app, or the official Durwella Unplugged Viz example app.

To create a simple view of the well model, a TumbleView can be used as follows:

1 using System;
2 using Durwella.Unplugged.Viz
3 using Xamarin.Forms;
4 
5 namespace Example
6 {
7  public class MyPage : ContentPage
8  {
9  public MyPage()
10  {
11  Content = new TumbleView
12  {
13  Models = { new WellModel() }
14  };
15  }
16  }
17 }

Licensing

The standard license received when purchasing Unplugged Viz through the Component Store will work indefinitely with no restrictions. The sample application included with the download is a special restricted license that should not be used for any other application.

Trial Licensing

The free Trial version of the component has substantially restricted functionality and should not be used in published apps. The restrictions in this version of the component include:

  1. Only ColorMappedPlotView<byte>, XYPlotView<byte>, and TumbleView can be used.
  2. Data are limited to byte[32,32] and byte[16] for ColorMappedPlotView<byte> and XYPlotView<byte>, respectively.
  3. TumbleViews are limited to 1 model with up to 128 vertices.
  4. CameraControls cannot be used.
  5. Only the common TextureMappedModel shaders can be used.

You may request a more full-featured license by requesting one at unplugged@durwella.com. Trial licenses should not be used for published apps. They offer no restrictions on functionality but are limited to 14 days from the time they are issued; any app using the component with an expired trial license will cease to function.

Standard License

You will receive your license key on purchase.

In your code, before calling the initialization code described above, set the property Durwella.Unplugged.Viz.License.Key to the string. Sample code is shown below.

1 public App ()
2 {
3  Durwella.Unplugged.Viz.License.Key = "{YOUR KEY HERE}";
4 
5  // The root page of your application
6  MainPage = new Example.MainPage();
7 }

If your license is an expired trial license, an Durwella.Unplugged.Viz.ExpiredLicenseException will be thrown when setting License.Key. If it's invalid for any other reason (or when accessing functionality not permitted by your licens) an Durwella.Unplugged.Viz.InvalidLicenseException will be thrown.