New version of best svg reader for .Net comes with new WinForms samples

by abenedik 30. September 2014 22:24

I am happy to announce that a new version of Ab2d.ReaderSvg has been published.

Read svg files in WinForms application

Let's start with a screenshot:

read svg file in WinForms application

As seen from the title of the window, this screenshot shows the new sample application that show how to read svg files in WinForms application with Ab2d.ReaderSvg library.

On the right side the image shows a scaled part of svg image – notice the nicely antialiazed scaled vector graphics where all the details are preserved when scaling. This part is shown with using an ElementHost control that can host WPF content in WinForms application. The content of the ElementHost control is set to a ZoomPanel control that allows users to zoom and pan the svg content.

The sample also shows a GDI+ bitmap in the lower left part of the application. It was created with reading the svg file with Ab2d.ReaderSvg library, then calling RenderToBitmap method (implemented in this version) to get WPF's bitmap and then converting the WPF's bitmap to GDI+ bitmap.

To summarize, the sample shows that it is very easy to read svg files in WinForms applications with Ab2d.ReaderSvg library. The recommended way is to use ElementHost control to preserve the vector graphics drawn by WPF. This way it is also possible to use the ZoomPanel control. When using ElementHost is not an option, it is also possible to convert the read svg file into GDI+ bitmap and show it inside PictureBox control.

 

Svg to png converter

This release also comes with a SvgToPngConverter console application. It can be used to batch convert many svg files into png files. It allows users to specify the bitmap size. Because the application comes with source code, it is possible to adjust it in any way. With uncommenting a few lines of code, the application can be changed to svg to jpg converter.

One possible usage of the SvgToPngConverter is to use it for online svg to png converter. The reason for that is that it is not recommended to use WPF objects inside web server (because potentially there can be some memory leaks that can become problematic when the web server is running for weeks or months). To overcome this problem, it is recommended to create WPF objects in a separate AppDomain or process. And the easiest way to do that is to use console application. So in our case, when the user (or Silverlight or some other client application) would upload svg file to the web server, the web server would call the SvgToPngConverter and provide the client with the created png file.

 

Those two samples should convince you that Ab2d.ReaderSvg can very successfully used to be read svg file in non WPF platforms also.

 

New features of Ab2d.ReaderSvg v5.5

Of course, there are also some other improvements and new features in the library.

The following is the full list:

  • Added RenderToBitmap method to render the read svg image to bitmap. The method allows users to render to custom bitmap size and to specify custom background brush.
  • Added FlattenHierarchy method that flattens the hierarchy of the read svg objects so that all the objects are children on one root Canvas.
  • Correctly handle "stroke-width" attribute in text element. Also does not convert text to path when stroke is set to some value but stroke-width is set to 0.
  • Fixed using some very small values for stroke thickness and values written in scientific format (1.23E-12).
  • Improved ReaderSvg startup and reading performance with optimizing Regex objects creation.

 

As always, if you find any svg files that do not open correctly or have any feature requests, please fill free to contact me.

Tags:

ReaderSvg

Improved performance and WinForms sample in new version of Ab3d.PowerToys

by abenedik 14. September 2014 22:52

I am happy to announce that a new version of Ab3d.PowerToys has been published.

The new version has the following new features:

  • Greatly improved performance of SphereVisual3D and BoxVisual3D.
  • Fixed updating 3D lines when Viewport3D is inside TabControl or when the Viewport3D is moved from one control to another (for example in Avalon dock when the docking of Viewport3D is changed)
  • Optimized LinesUpdater to minimize the number of newly created object each rendering frame.
  • Added WinForms sample that shows how easy is to show 3D graphics in WinForms with embedded WPF and Ab3d.PowerToys

The biggest new feature is performance improvement that is achieved by caching the MeshGeometry3D for the sphere and box models. Before each time the position or size of the sphere or box was changed, the whole MeshGeometry3D was regenerated. Now all the spheres (with the same segment count) and boxes share the same MeshGeometry3D. To create the sphere and box at the specified position and size, a MatrixTransform is used.

The biggest performance gain of the new rendering is get when the spheres and boxes are animated – when the position or size is changed. Because now it is not needed to recreate the whole MeshGeometry3D the animation can be much smoother – on some computers even more than 20 times faster.

Because the new model generation algorithm reuses the MeshGeometry3D, much less data is sent to graphics card and therefore the models can be rendered much faster. On some computers more than 5 times better frame rate can be achieved. 

To test the new functionality a new sample was added to the Ab3d.PowerToys samples. The following screenshot shows the sample running and showing the number of spheres, triangles and positions and the current frame rate (on Intel i7 3770 and a more than 2 years old NVidia 560 GTX Ti):

WPF 3D performance with Ab3d.PowerToys

 

Sceptics of WPF 3D can see that when WPF 3D is used property it can have quite decent performance – animating (changing size) for 3375 spheres (more than 3 million triangles and more than 17 million positions) runs at 33 frames per second.

The new sample can be also very appealing visually – the following image shows one of such interesting screenshots (animated version is even better):

WPF 3D performance with Ab3d.PowerToys

 

Delivering the best possible performance for WPF 3D graphics have always been our goal. Therefore I am planning to add some additional performance improvement to the next version – this time improving performance of complex 3D models read with Reader3ds or some other model importer.

I would also like to say a few more things about using WPF 3D inside WinForms application. 

And now to WinForms. Surprisingly a lot of .Net developers are still using WinForms. For them I have prepared two samples that shows how easy is to add 3D graphics to WinForms. It is not needed to spend half a year to learn DirectX or some other game engine. With using ElementHost control the developers can enjoy in using the easiest 3D API: WPF 3D with Ab3d.PowerToys.

The first sample that comes with the new version of Ab3d.PowerToys library show that with a little bit more than 200 lines of c# code, it is possible to create an interesting 3D scene with dynamic objects that change color on mouse actions. The following image shows a screenshot of the sample:

WPF 3D inside WinForms

 

WinForms developer will be glad to hear that that do not need to use XAML, binding or any other new concept that is introduced by WPF. 

On the other hand the second sample shows that it is also possible to define the whole 3D scene in XAML. When using WinForms designer this scenario is very well supported: after adding ElementHost to the form, it is possible to click on a small right arrow in the upper right corner and from a drop down menu select from all the WPF’s UserControls in the solution. This way it is possible to design the scene in XAML and use Visual studio designer to preview the 3D scene.

 

I would like to conclude this blog post with the following announcement: I am already working on next major released of Ab3d.PowerToys. It will contains the already mentioned functionality to optimize the 3D models for best performance. But the biggest new feature will be added support for importing 3D models from almost all 3D file formats.

Tags:

Ab3d.PowerToys

New major release of Ab2d.ReaderWmf (metafile importer for WPF) is available

by abenedik 12. July 2014 15:56

I am happy to announce that I have just released a new major release of Ab2d.ReaderWmf library. This adds some great new features to the best metafile importer for WPF.

Metafiles are usually rendered with GDI+ rendering engine. Because there are many differences between GDI+ and WPF, some metafile features cannot be rendered in WPF. Until now such a problematic feature was usage of patterns and specific bitmap function (dwRop) in metafiles. They were used many times to darken or lighten the color of shapes. The following image shows how such metafile can look when it is imported into WPF:

Until now, this could be prevented by disabling patterns. This showed the shapes with using the original color:

But the results were quite far from the original colors. 

The new version of ReaderWmf analyzes the pattern and the used bitmap function and determines how the original color should be changed. Using this new logic produces the accurate results:

The following is another example of using pattern brushes with shadows in some Word shapes:

With new version of ReaderWmf the result is correct:

As always the new version also brings some other new features and fixes. Here is the full list:

  • Added ConvertPatternBrushesToColor to ReaderWmf - use data from pattern brush to change the color of the shape
  • Added DisableTextScaling property - in case text is wrongly scaled, user can disable scaling of text
  • Improved reading geometries when rectangle or ellipse have both Canvas position (Canvas.Left or Canvas.Top) and transformation set.
  • Improved xaml writer to prevent writing Canvas.Left = "0" and Canvas.Top = "0" (zero values can be skipped).
  • Prevented writing "Canvas.Left" and "Canvas.Top" properties in XAML two times.
  • Added IgnoreRootElementSize property to GeometrySetting - added possibility to remove the transformations or RectangleGeometry based on the size or root element.
  • Fixed problems where some separate lines were connected with additional line but they should not be.
  • Improve reading metafiles that have negative width or height specified in metafile header
  • Prevented throwing "The method or property is only available in Professional version!" under some circumstances.
  • Fixed not showing some texts under some circumstances.

Tags:

ReaderWmf

New version of Ab3d.PowerToys brings improved support for touch and better user experience when rotating the camera

by abenedik 19. June 2014 22:26

Touch and multi-touch support is becoming more and more important. The previous version of Ab3d.PowerToys had only basic touch support – it supported only those touch events that were transformed into mouse events. To get better touch support users needed to use MultiTouchMouseCameraController class that was available in a separate project.

The new version adds excellent touch and multi-touch support to the core of the Ab3d.PowerToys library. This means that without any change in your code, the users of your application that will have touch screen will be able to rotate and move the camera with touch and also use pinch to zoom in and out. New MouseCameraController has many new properties that can be used to configure the touch actions.  To get full control of touch events, you can override some methods that control the behavior of MouseCameraController. See help file for more information.

To further improve the user experience, the new version now also adds camera rotation velocity inertia. This means that if user rotates the camera and then released the mouse button (or touch), the velocity of the camera rotation is preserved and the camera’s rotation is stopped slowly. This looks much more naturally, especially when used with touch.

The new rotation easing is now also supported by StartRotation and StopRotation methods. Now it is possible to start and stop rotation with slowly accelerating / decelerating the rotation velocity.

The last new feature is related to HeightMapVisual3D. Now when the data that is set to HeightData is changed, it is possible to call the new UpdateContent method to update the 3D model of the height map.

 

I hope you and your customers will like the new features. If you have any additional requests or ideas, please do not hesitate to contact us.

Tags:

Improved version of Ab2d.ReaderSvg and Ab2d.ReaderWmf available

by abenedik 23. May 2014 21:43

I am happy to announce that a new version of Ab2d.ReaderSvg and Ab2d.ReaderWmf have been published.

I am particularly proud of adding some very interesting hierarchy optimizations to ReaderSvg. Drawings in svg files are many times defined in many groups and with using transformations. In case you do want to simply show your vector assets, than it is much more convenient to have the drawing objects compact and without the complex hierarchies. With the new version of ReaderSvg this is not very easy task. More about that later in this post.

First let me show what is new for Ab2d.ReaderWmf – metafile reader for WPF:

  • Improved reading geometries when rectangle or ellipse have both Canvas position (Canvas.Left or Canvas.Top) and transformation set.
  • Improved xaml writer to prevent writing Canvas.Left = "0" and Canvas.Top = "0" (zero values can be skipped).
  • Prevented writing "Canvas.Left" and "Canvas.Top" properties in XAML two times.
  • Added IgnoreRootElementSize property to GeometrySetting - added possibility to remove the transformations or RectangleGeometry based on the size or root element.
  • Fixed not showing some texts under some circumstances.

Most of the improvements in ReaderWmf are also available in ReaderSvg. Here is the full list:

  • Clip path now works on all elements and not just on Canvas.
  • Improved size measurement when AutoSize is set to true and some objects are hidden.
  • Added objects grouping optimizations to ReaderSvg - they can be controlled by new properties in ReaderSvg: OptimizeObjectGroups, FlattenHierarchies, TransformShapes
  • Improved transforming read objects with calling Transform method.
  • Updated SvgBounds after calling Transform method with updateLastReadViewbox set to true.
  • Prevented throwing exception in GetObjectsWithCustomProperties when svg file does not have any custom properties.
  • Added IgnoreRootElementSize property to GeometrySetting - added possibility to remove the transformations or RectangleGeometry based on the size or root element. This can produce nicer XAML.
  • Fixed using transformations on EllipseGeometry and RectGeometry when reading svg file as geometry.
  • Prevented writing "Canvas.Left" and "Canvas.Top" properties in XAML two times.
  • Improved reading geometries when rectangle or ellipse have both Canvas position (Canvas.Left or Canvas.Top) and transformation set.
  • Improved XAML writer to prevent writing Canvas.Left = "0" and Canvas.Top = "0" (zero values can be skipped).

As mentioned before ReaderSvg now support optimizing groups. The best way to describe this new functionality is to show it in action. Let’s start with the following XAML that can be get when using no optimization:

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="200" Height="100">
    <Canvas>
        <Canvas Name="g1">
            <Rectangle Fill="Yellow" Width="200" Height="100"/>
            <Canvas Name="g2">
                <Canvas Name="g3">
                    <Ellipse Name="e1" Fill="Red" Width="20" Height="20"/>
                    <Canvas Name="g4">
                        <Canvas Name="g6" RenderTransform="2,0,0,1,-60,-10">
                            <Canvas Name="g5" Canvas.Left="50" Canvas.Top="10">
                                <Ellipse Name="e2" Fill="Green" Width="20" Height="20" Canvas.Left="10" Canvas.Top="10"/>
                                <Canvas Name="g7" RenderTransform="0.5,0,0,1,20,20">
                                    <Canvas Name="g8">
                                        <Canvas Name="e3" RenderTransform="1,0,0,2,20,0">
                                            <Ellipse Fill="Blue" Width="20" Height="20" Canvas.Left="20"/>
                                        </Canvas>
                                    </Canvas>
                                </Canvas>
                                <Canvas Name="g9" RenderTransform="5,0,0,5,0,0">
                                    <Canvas Name="g10">
                                        <Ellipse Name="e4" Fill="Orange" Width="4" Height="4" Canvas.Left="11" Canvas.Top="3"/>
                                    </Canvas>
                                </Canvas>
                                <Canvas Name="g11" Canvas.Left="-10" Canvas.Top="30">
                                    <Polygon Name="p1" Points="10,10 30,10 20,20" Fill="Lime" StrokeThickness="1"/>
                                    <Canvas Name="g12" RenderTransform="1.5,0,0,1,0,10">
                                        <Polygon Name="p2" Points="10,10 30,10 20,20" Fill="Aqua" StrokeThickness="1"/>
                                        <Canvas Name="g13" RenderTransform="0.866025388240814,0.5,-0.5,0.866025388240814,0,0">
                                            <Polygon Name="p3" Points="10,10 30,10 20,20" Fill="Purple" StrokeThickness="1"/>
                                        </Canvas>
                                    </Canvas>
                                </Canvas>
                            </Canvas>
                        </Canvas>
                    </Canvas>
                </Canvas>
            </Canvas>
        </Canvas>
    </Canvas>
</Canvas>

The XAML shows that there are many Canvases that contains only other Canvases. In the first step we can set OptimizeObjectGroups to true. This reduces the size of XAML to:

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="200" Height="100">
    <Canvas Name="g1">
        <Rectangle Fill="Yellow" Width="200" Height="100"/>
        <Canvas Name="g3">
            <Ellipse Name="e1" Fill="Red" Width="20" Height="20"/>
            <Canvas Name="g5" RenderTransform="2,0,0,1,40,0">
                <Ellipse Name="e2" Fill="Green" Width="20" Height="20" Canvas.Left="10" Canvas.Top="10"/>
                <Canvas Name="e3" RenderTransform="0.5,0,0,2,30,20">
                    <Ellipse Fill="Blue" Width="20" Height="20" Canvas.Left="20"/>
                </Canvas>
                <Canvas Name="g10" RenderTransform="5,0,0,5,0,0">
                    <Ellipse Name="e4" Fill="Orange" Width="4" Height="4" Canvas.Left="11" Canvas.Top="3"/>
                </Canvas>
                <Canvas Name="g11" Canvas.Left="-10" Canvas.Top="30">
                    <Polygon Name="p1" Points="10,10 30,10 20,20" Fill="Lime" StrokeThickness="1"/>
                    <Canvas Name="g12" RenderTransform="1.5,0,0,1,0,10">
                        <Polygon Name="p2" Points="10,10 30,10 20,20" Fill="Aqua" StrokeThickness="1"/>
                        <Canvas Name="g13" RenderTransform="0.866025388240814,0.5,-0.5,0.866025388240814,0,0">
                            <Polygon Name="p3" Points="10,10 30,10 20,20" Fill="Purple" StrokeThickness="1"/>
                        </Canvas>
                    </Canvas>
                </Canvas>
            </Canvas>
        </Canvas>
    </Canvas>
</Canvas>

But there are still many Canvases. A more radical step is to remove the all the hierarchies. This can be simply done with setting FlattenHierarhy to true (OptimizeObjectGroups can be set to false). The results speak for themselves:

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="200" Height="100">
    <Rectangle Fill="Yellow" Width="200" Height="100"/>
    <Ellipse Name="e1" Fill="Red" Width="20" Height="20"/>
    <Ellipse Name="e2" Fill="Green" Width="20" Height="20" RenderTransform="2,0,0,1,40,0" Canvas.Left="20" Canvas.Top="10"/>
    <Ellipse Fill="Blue" Width="20" Height="20" RenderTransform="1,0,0,2,100,20" Canvas.Left="20"/>
    <Ellipse Name="e4" Fill="Orange" Width="4" Height="4" RenderTransform="10,0,0,5,40,0" Canvas.Left="110" Canvas.Top="15"/>
    <Polygon Name="p1" Points="10,10 30,10 20,20" Fill="Lime" StrokeThickness="1" RenderTransform="2,0,0,1,20,30"/>
    <Polygon Name="p2" Points="10,10 30,10 20,20" Fill="Aqua" StrokeThickness="1" RenderTransform="3,0,0,1,20,40"/>
    <Polygon Name="p3" Points="10,10 30,10 20,20" Fill="Purple" StrokeThickness="1" RenderTransform="2.59807616472244,0.5,-1.5,0.866025388240814,20,40"/>
</Canvas>

With using just one simple property we have come from a complex hierarchy to one simple Canvas that contain all the objects. But we can go even one more step further. As seen in the last step, almost all the objects use RenderTransform to transform them. With setting TransformShapes to true we can eliminate almost all RenderTransforms from the objects. So after setting both FlattenHierarhy and TransformShapes to true, we are left with the following XAML:

<Canvas xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="200" Height="100">
    <Rectangle Fill="Yellow" Width="200" Height="100"/>
    <Ellipse Name="e1" Fill="Red" Width="20" Height="20"/>
    <Ellipse Name="e2" Fill="Green" StrokeThickness="1.414" Width="40" Height="20" Canvas.Left="60" Canvas.Top="10"/>
    <Ellipse Fill="Blue" StrokeThickness="1.414" Width="20" Height="40" Canvas.Left="120" Canvas.Top="20"/>
    <Ellipse Name="e4" Fill="Orange" StrokeThickness="7.071" Width="40" Height="20" Canvas.Left="150" Canvas.Top="15"/>
    <Polygon Name="p1" Points="40,40 80,40 60,50" Fill="Lime" StrokeThickness="1.414"/>
    <Polygon Name="p2" Points="50,50 110,50 80,60" Fill="Aqua" StrokeThickness="1.732"/>
    <Polygon Name="p3" Points="30.981,53.66 82.942,63.66 41.962,67.321" Fill="Purple" StrokeThickness="1.732"/>
</Canvas>

Nice and clean!

No more transformations. Instead the values of the shapes were transformed to give us clean and simple object model.

Note that when the Canvas defines the clipping area, than even when FlattenHierarhy is set to true, this Canvas is preserved. This way the end results are still the same as with having the whole hierarchy. 

In the same fashion, the TransformShapes could preserve some RenderTransforms. This happens when it is not possible to preserve the object with only transform the object’s values – for example if Ellipse or Rectangle is rotated with RenderTransforms,  then we cannot preserve this rotation without using transformation (with Ellipse and Rectangle we can only change the position and size).

I am sure that those new features are great for anyone that wants to use vector assets instead of bitmap. I think that using vector assets is the future. They have many advantages over bitmaps. For example they are DPI independent and can be scaled up and down without any loss. They usually take less space on disk. They can be simply manipulated – for example if you want that one icon changes color when the mouse is over it, this can be done with simply changing the Stroke or Fill color. With bitmap you need to use provide the bitmaps in all possible colors.

Therefore I am already working on a new application that will allow users to simply create ResourceDictionaries with many vector objects created from svg or metafiles. The application will allow the user to optimize and transform the objects before they are added to ResourceDictionary. For example it will be possible to create vector assets that will all have the same size and the same padding regardless from which source they are created. And what is more, the application will be available with full source code.

At the end of this post I would like to remind you, that the XAML that is created with our converter applications (ViewerSvg and Paste2Xaml) are not meant only for WPF. They can be also used for Silverlight and also for Windows Phone and Windows Store apps.

Tags: ,

ReaderSvg | ReaderWmf

3D visualization of Kinect skeleton

by abenedik 11. April 2014 10:14

In this blog post I will show you how easy is to show Kinect skeleton as a 3D model.

Ab3d.PowerToys Kinect sample

To jump start into 3D programming we will be using WPF and Ab3d.PowerToys library. The library will help us with providing the standard 3D models that will be used to display the skeleton and cameras that can be easily controller by the user.

The image above shows us that the skeleton is created from yellow spheres that represent the joints and bi-pyramids are used to connect the joints together. To make the sample more interesting the skeleton has a Darth Wader’s head. Below the skeleton model a 3D wire grid is shown. It represents the floor.

In the lower right corner three different types of arrow buttons are shown. They can be used to control the camera – move, rotate and zoom in / out the camera. They are created by simply adding CameraControlPanel to the Window. Camera can be controlled also without using buttons. The MouseCameraController lets you rotate the camera with holding down the left mouse button, zoom in and out with mouse wheel and move the camera with holding control key and left mouse button. The MouseCameraController also provides easy way to specify different combinations of keys and mouse buttons for rotate and move actions.

Before diving into the code that shows the 3D model, let’s quickly look how we get the required 3D data from Kinect. Kinect SKD can provide real time skeleton and depth data. To make the sample work without having an actual Kinect device and an actual actor in front of the sensor, the Kinect data was saved into files with using Kinect Toolkit (an open source helper library). This way we can replay the recorded data any time we want.

For each recorded frame we get data for all recorded skeleton models. For each skeleton we get collection of joints and BoneOrientation objects. With them it is quite easy to get the actual 3D positions of the joints and the transformations (rotations and translations) applied on each of the joint. Once we have that data we can start on code that will show our 3D model.

In our sample we can show the 3D model in 4 different ways.  User can change that by selecting different value in the “Skeleton display mode” ComboBox. The following are the available options:

  • Lines,
  • Pyramids,
  • BiPyramids,
  • TransformedBiPyramids


Using 3D lines

The simplest solution to show 3D model is to show it with 3D lines. Actually, if we would be using only standard WPF 3D objects without Ab3d.PowerToys, this would be the hardest solution to implement. The problem is that WPF 3D does not have native support for 3D lines and therefore they need to be created manually by defining the triangles that would show 3D line. Luckily Ab3d.PowerToys library adds that support to WPF. With the Ab3d.PowerToys library the code to add 3D line between two joints is the following:

AddSkeletonLines(Point3D startPoint, Point3D endPoint)
{
    var lineVisual3D = new LineVisual3D()
    {
        StartPosition = startPoint,
        EndPosition = endPoint,
        LineColor = Colors.Green,
        LineThickness = _skeletonThickness * 100.0
    };

    Placeholder3D.Children.Add(lineVisual3D);
}

The following image shows how the skeleton is shown when using 3D lines:

Ab3d.PowerToys Kinect sample

Note that it is very easy to define the line thickness.

Using pyramids

Using 3D lines already gives you some 3D feeling of the model, especially because you can rotate the camera around the model and observe it from any angle.

To give the model a better 3D look, we will use 3D pyramids to connect joints.

Because we need to orient the pyramid model based on start and end position, we cannot use standard pyramid model from Ab3d.PowerToys library. Instead we need to use a low level object - DirectedPyramidMesh3D. It can create a MeshGeometry3D that represent a pyramid oriented in such a way that the pyramid’s center is defined by start point and the pyramid’s top is define by end position.

The following screenshot shows the skeleton displayed with pyramid:

Ab3d.PowerToys Kinect sample

Using bi-pyramids

Pyramids already gave us a better 3D representation that is more similar to actual 3D person model. But this can be further improved with using bi-pyramids. Bi-pyramids are objects that are created with combining two pyramids together.

We could easily create bi-pyramid with using two objects created with DirectedPyramidMesh3D. All we needed to do is to use the end position of the first directed pyramid as the start position of the second directed pyramid.

But to demonstrate some advanced features of the Ab3d.PowerToys we will create bi-pyramids with using lathe 3D objects. Lathe 3D object is an object that is defined by a 2D shape and start and end position. The 2D shape is than rotated around an axis defined by start and end position. This creates a 3D object – typical lathe objects are glasses and vases.

The following image shows a screenshot from samples that come with Ab3d.PowerToys library and show how a lathe 3D object was created (the 2D shape is shown on the right with red line):


The 2D shape used to define the lathe object is defined by LatheSections. Bi-pyramid is actually one of the simplest lathe objects possible – it requires only one section definition. This section defines how wide the bi-pyramid is.

After implementing the creation of bi-pyramids our skeleton looks like the first image in this blog.

From the list of display mode options you can see that it is also possible to show the skeleton as TransformedBiPyramids. This option shows the same skeleton as with bi-pyramids, but instead of using start and end position to define the object orientation, this time the transformation of the joint is used to rotate the bi-pyramid. This option provides a possible optimization. It can be achieved by creating the bi-pyramid model only once and then apply different transformation to it.

Similar optimization was used for showing joint spheres. Here we create only one instance of sphere GeometryModel3D and then use different transformations to position and scale the individual joint models around the skeleton.

The only thing yet to describe is how the head was created. We used a Darth Wader image and use it as a texture shown on a 3D plane. Once we have the position of the head and a head transformation, it is super easy to add Darth Wader head to the skeleton:

// Add head - show image for head
var headPosition = skeleton.Joints[JointType.Head].Position.ToPoint3D(_skeletonScale) + offset;

var headPlane = new PlaneVisual3D()
{
    CenterPosition = headPosition,
    Material = _headMaterial,
    BackMaterial = _headMaterial,
    HeightDirection = new Vector3D(0, 1, 0),
    Normal = new Vector3D(0, 0, 1),
    Size = new Size(_skeletonScale * 0.3, _skeletonScale * 0.3),
    Transform = skeleton.BoneOrientations[JointType.Head].AbsoluteRotation.ToRotateTransform3D(headPosition)
};

Placeholder3D.Children.Add(headPlane);

Adding special model for head finishes our 3D visualization of Kinect skeleton.

As you have seen, having the right tools makes the job very easy. And Ab3d.PowerToys library contains the ultimate collection of tools to add 3D content to your .Net application very easy. More about the library can be read from Ab3d.PowerToys web page.

The sample with full source code is available with Ab3d.PowerToys library. The trial version of the library can be downloaded from downloads page.

Tags:

Ab3d.PowerToys

New version of Ab3d.PowerToys with better wireframe support and many other improvements

by abenedik 2. April 2014 21:19

I am very happy to announce that a new version of Ab3d.PowerToys is available.

The biggest new feature of the new version is a new WireframeVisual3D class. It can be used to show a 3D model with wireframe rendering. You just need to set a 3D model to OriginalModel property (or set the model as content in XAML) and then decide how you want to show the model and set the WireframeType property accordingly – you can show the model as wireframe only, as wireframe with solid model (can be also used to create wireframe with hidden lines) or as solid model only. What is more, the wireframe color can be fixed (for example all lines black) or the color of the lines can be determined by the color of the model’s material. The same choice can be made for solid model – it can be shown with original color or with fixed color.

The following two screenshots show two sample usages (screenshots from new samples that come with the library):

<visuals:WireframeVisual3D WireframeType="WireframeWithSingleColorSolidModel"
 LineThickness="2" UseModelColor="True" SolidModelColor="Black" > 
     <GeometryModel3D> …

WireframeVisual3D sample 1

 


<visuals:WireframeVisual3D WireframeType="WireframeWithOriginalSolidModel"  LineThickness="2" LineColor="Black" UseModelColor="False" >      <GeometryModel3D> …

WireframeVisual3D sample 1

 

What is more, the code in the new DXEngine (DirectX rendering engine that is being developed by AB4D) is specially optimized to render the wireframe and solid model in the most efficient way.

The new Ab3d.PowerToys also uses an improved algorithm for triangulation. Triangulation is used to create a 3D model (define triangles) from a 2D polygon. The code in the previous version used another version of algorithm that had some problems with some of the polygons. The new code is much better and should handle all possible polygons. But it does not support polygons with holes.

There is also a new DirectedPyramidMesh3D object that can be used to create a pyramid that is facing its peat to the specified direction.

And as always there are also some other improvements and bug fixes. The following is a list of all the changes:

  • Added WireframeVisual3D to simplify showing models with wireframe.
  • Improved triangulator - before in some cases a wrongly triangulated object was returned or an "Improperly formed polygon" error was thrown.
  • Added DirectedPyramidMesh3D to create a pyramid object that is oriented in a specified direction.
  • Added Ab3d.Utilities.ModelUtils class that contains ChangeMaterial (change material on all child Model3D objects) and CopyModel (copy child Model3D objects) methods.
  • Improved 3D Lathe creator - now it is allowed to specify only one segment when start and end positions are closed.
  • Added GetPerpendicularVectors to MathUtil - calculate two vectors that are perpendicular to the input vector.
  • Fixed calling PreviewCameraChanged and CameraChanged events when CameraWidth is changed in Orthographic camera.
  • Fixed Point3DTo2D and Rect3DTo2D if size of Viewport3D is changed or if CameraWidth in Orthographic camera is changed.
  • Added Dump extension methods that can dump (write to Debug console) various WPF 3D objects (Matrix3D, Model3D, Geometry3D, Transform3D, Material, Rect3D). This is very useful to get detaled information in Visual Studio Immediate Window - Window – for example you can write "Ab3d.Utilities.Dumper.Dump(myModel3D)".
  • Added GetWorldToViewportMatrix method to BaseCamera.
  • Fixed Creating wireframe with WireframeFactory when model groups have transformations.
  • Cleaned the code to remove compiler warings when compiling source code.
  • Added overrides to CreateWireframe with additional removedDuplicates parameter - when the parameter is true this can significanlty increase time to create wireframe model, but creates less lines because duplicate lines are removed (this was used in the previous version). Not it is possible to set removedDuplicates to false to greatly reduce the initial creation time but end up with having more 3D lines. This can be user when rendering the lines with DXEngine were rendering lines is super-fast compared to WPF 3D where it is very slow.
  • Added Microsoft Kinect 3D player sample.

 

The list of changes in the Ab3d.PowerToys library ends here. But this is not everything that is new is the new version. There is also a brand new sample project. It was developed with help of a customer that wanted to show the 3D skeleton that was captured with Microsoft Kinect with a 3D model where the user can rotate the camera around the model.

The sample showed again that when having the right tools (Ab3d.PowerToys in this case), it is very easy to create an application that show 3D models and allow user to rotate and move the camera around. You can check the sample with downloading the latest version of the library (note: you will need to install Microsoft Kinect SDK). I will write a separate blog post with more details about that sample in the following days. For now here is a screenshot of the sample:

WireframeVisual3D sample 1

Tags:

Ab3d.PowerToys