New DirectX rendering engine for 3D graphics in .Net applications is available

by abenedik 7. September 2015 15:28

I am very proud to present you a brand new DirectX 11 rendering engine – Ab3d.DXEngine.

The main purpose of the new engine is to bring you two mutually exclusive things: great power of DirectX and super easy to use WPF 3D API. 

Using WPF 3D API means that there is already a lot of documentation and samples on the internet and in the books. What is more, the existing WPF application that show 3D graphics can be preserved and with only a few little changes converted into DirectX powered applications.

 

You can already try the release candidate version of the new engine – it is available from our downloads page as part of the trial products installer.

 

The road to the Ab3d.DXEngine was not easy and short. Creating a rendering engine is not an easy task. The following picture shows my pile of DirectX related books (I have started with learning XNA and then moved to pure DirectX; countless articles on the web are not photographed):

DirectX books

Working with DirectX is not easy. You need to understand many new concepts that are quite different from the traditional development used when developing standard applications. The amount of required knowledge is huge – you need to understand how modern graphics cards work, understand DirectX API with all its methods and properties and finally understand how to program graphics shaders and how to use GPU debugging tools. And it is not enough that you are satisfied with the rendered image. Everything also need to be optimized as much as possible for performance and memory usage. To achieve 60 frames per seconds, the whole rendering code have only 16 milliseconds to render all the objects (in reality there is less time than 16 ms available because of WPF overhead). Because rendering usually happens at 60 frames per second, the rendering code is executed a lot of times. This means that you need to be especially careful with memory usage. Every small memory inefficiency can become a big memory leak in minutes. This also means that creating new objects should be avoided to minimize running garbage collector.

So, working with DirectX is quite challenging. And probably even more challenging was to make the existing WPF 3D API work well with completely different DirectX API.

But the really great news is that you will not need to bother with all that complexity anymore because the new Ab3d.DXEngine allows you to use DirectX with the comfort of the WPF 3D API.

To make the transition from the WPF 3D rendering to DirectX rendering, you will only need to add one element to your XAML (sometimes some additional smaller changes are needed – see Ab3d.DXEngine help file for more info; it is also advisable to add some additional configuration options).

Instead of standard WPF 3D rendering:

<Viewport3D Name=" width="360" height="471"" />
        <!-- WPF Viewport3D content -->
    </Viewport3D>

You will need to enclose the Viewport3D into DXViewportView:

<dxControls:DXViewportView Name="MainDXViewportView">
    <Viewport3D Name="MainViewport">  
        <!-- WPF Viewport3D content -->
    </Viewport3D>  
<dxControls:DXViewportView>

This means that you can preserve the existing WPF 3D solutions and with just minimal changes you can achieve great improvements in rendered graphic.

 

This leads us to the advantages of using DirectX rendering over WPF 3D rendering.

The biggest advantage of the new rendering engine is that it is fully customizable (it will be also possible to buy full source code). You can create your own shaders, effects or otherwise change the rendering process. This also solves the biggest problem of WPF 3D – it was a closed box with no way to change it.

Another advantage of the Ab3d.DXEngine is the speed of rendering. Simply by using DirectX 11 instead of DirectX 9 (that is used by WPF) means that there will be performance improvements because of lower API overhead (less time is spend in DirectX and graphics card driver’s code). Additional improvements can be achieved because of more advanced API. For example WPF uses only 16 bit index buffer. This means that it can render 65535 triangle indices with one draw call. So if you are rendering an object with one million triangles, this means that 3 million triangle indices is needed – so WPF needs to split that into 46 separate index buffers and require 46 draw calls (one draw call is a DirectX method that issues drawing on the graphic card – lowering the number of draw calls is the easiest and most efficient method to improve performance). On the other hand, Ab3d.DXEngine uses 32 bit index buffer so it can render the same object with only one draw call. 

For example the Predator model from the following screenshot has only a single GeometryModel3D with 2.9 million positions:

Predator 3D model rendered with Ab3d.DXEngine

On NVIDIA GTX 970 and i7 3770 and with Ab3D.DXEngine it can be rendered in 0.3 milliseconds (theoretically allowing more than 3000 frames per second). With WPF 3D rendering the frame rate drops to only 14 frames per second.

 

The performance gains do not come only from DirectX API improvements but also from the design of the Ab3d.DXEngine. The engine internally organizes the objects in such a way that the number of draw calls and state changes is as low as possible and therefore rendering can be very fast.

The performance gains are even bigger when WPF objects are frozen (Freeze method is called on them). In such case Ab3d.DXEngine aggressively reorganizes and combines the models so that they are rendered blazingly fast.

I am also happy that the Ab3d.DXEngine eliminates the most common performance problem in WPF 3D – rendering many 3D lines. In WPF 3D rendering many 3D lines really kills the performance. The problem is that 3D lines need to be converted into triangles and each time the camera was changed all the triangles needed to be recalculated. This requires a lot of CPU time. In Ab3d.DXEngine this problem does not exist because the 3D lines can be very efficiently generated on graphics card in its geometry shader – so the Ab3d.DXEngine just send the 3D lines data (collection of start and end positions) to GPU and it rendered the lines very efficiently.

For example the wireframe scene from the following screenshot is rendered in around 0.7 ms (theoretically allowing around 1400 frames per second) when using Ab3d.DXEngine and gets only 3 frames per second when WPF 3D is used (on NVIDIA GTX 970 and i7 3770):

Wireframe ship model rendered with Ab3d.DXEngine

The list of performance improvements is not over. The Ab3d.DXEngine allows hardware instancing. This can achieve incredible performance gains when many instances of the same geometry need to be shown. Usually this is rendered in such a way that each instance is rendered individually and the position of the instance and its color is sent to GPU with its own draw call. When using instancing instead of drawing each instance individually we draw all instances at once – here we use a special draw command that requires data of the geometry and an array of colors and world matrixes (define the position, scale and rotation of each instance). So instead of many draw calls we can use only one.

 

Another advantage is that the it Ab3d.DXEngine can render graphics in much better quality. The biggest difference is that WPF is using per-vertex lighting and Ab3d.DXEngine is using per-pixel lighting. This means that in WPF lighting calculations are done only for each vertex. Then the colors are interpolated between vertexes. In Ab3d.DXEngine the lighting calculations are done for each displayed pixel. This is best seen in the following screenshot where WPF rendering is on the left and Ab3d.DXEngine rendering is on the right (note the accurate spot light cone and accurate reflections on the sphere – despite having low number of segments):

Comparison between WPF and Ab3d.DXEngine

The image above shows that the rendered quality is already significantly improved. But because Ab3d.DXEngine can get easily customized, it will be possible to add many great visual effects in the future.

 

I am planning to add support for shadow mapping. Actually I already have a working sample, but it still needs some polishing to be publicly available:

Shadow mapping in Ab3d.DXEngine

Shadow mapping is only one of the effects that will be added to the engine. I am also planning to add support for environmental maps (enabling natural looking reflections on metallic objects), screen space ambient occlusion (adding subtle shadows that make objects look more realistic), bump mapping, depth of field, etc. Because of the open nature of the engine this list is practically endless.

 

I would also like to point out one aspect of the new engine. It allows you to slowly get familiar with DirectX and graphic shaders. Usually if you would like to add DirectX to your application, you need to acquire a lot of new knowledge – how to set up DirectX environment, prepare the buffers, render objects, write graphic shaders and lots of other tiny details that each must work or you will see just a black screen. The great thing that Ab3d.DXEngine brings is to allow you to slowly dive deeper and deeper into the DirectX world. You can start with simple WPF 3D API – cameras, lights and models (geometry with material). Then you can use the source of the existing shaders and play with it. This will slowly introduce you to the hlsl shaders language. After that you can try to create your own shaders that require different constant buffers or input semantics. You can also prepare special objects that use some other draw methods. (note that the current version does not come with shaders source code; also I would recommend to wait until version 1.1 – the reason is that I am planning to significantly change the layout of the constant buffers and will also focus on improving support for custom shaders).

 

I would also like to quickly describe the difference between the Ab3d.DXEngine and many other DirectX game engines. 

There are really many different game engines available – from top class engines for AAA games to free and open source game engines. As the name implies, the main purpose of the game engine is to build a game. This means that a product of a game engine is a package with its own executable and many game resources. The user of the game engine spends most of his time in the game editor where he designs game levels, defines model properties and write some scripts.

If you want to create a business application that requires some 3D graphics, you could theoretically still use a game engine to render the 3D graphics. But practically this would mean that you will need to hack the engine to become something that it was not designed for. You will also need to significantly change your application to meet the constraints of the game engine.

On the other hand the Ab3d.DXEngine was designed to be used in business applications. 

The biggest advantage of this design is that it is very easy to integrate the 3D graphics into existing user interface. For example, a thing that all WPF developers take for granted is to be able to mix layout elements so that you can place elements on top of each other. Also if an element on top has some transparent parts, the elements below will be visible. This is something that is almost impossible to achieve when using game engine – game engines complete the frame drawing with calling the DirectX Present method – this method requires that SwapChain is used and the SwapChain requires its own window handle – practically this means that the area of screen that is used by the 3D engine cannot be used by any other application. This means that you cannot put a button on top of the 3D scene. With the Ab3d.DXEngine the rendered image can be used just as any other WPF element (this is the default presentation type - DirectXImage; with simple change of a PresentationType property you can change that to DirectXOverlay presentation type that uses the same presentation technique as game engines – this is needed when you want to use graphics debugging tools).

The engine is also optimized to support the most common use cases for 3D graphics in business applications. For example the engine supports both perspective and orthographic cameras. The engine can also easily render back face materials (rarely used in game engines). There is also a very good support for object picking and for rendering 3D lines and wireframe models.

And finally, you do not need to learn C++ to use DirectX. You can stay in the most efficient environment for developing application - .Net. Note that Ab3d.DXEngine is primarily meant to be used in WPF application, but it can be also easily used in WinForms applications.

 

I would really like to invite you to try the new rendering engine. It can be downloaded from our Downloads page as part of the products trial. The engine also works well with the Ab3d.PowerToys library (though it is recommended to use the lasts 7.1 version – it also works with older version but you might need to adjust some things – see the DXEngine’s help file for more info). If you already have an older commercial version of Ab3d.PowerToys installed, you can still safely install the latest trial version (you will need to manually enable the Ab3d.PowerToys in the installer at the products selection page). 

If everything goes well, I am going to release the Ab3d.DXEngine in October 2015. 

This will be only the first version of the engine. It will not contains all the goodies of DirectX graphics like shadow mapping and other effects. But it will already have enough powerful features to significantly improve your existing WPF 3D applications. And one of its main purposes is also to establish a good foundation for the future expansions.

If you would like to receive news about the Ab3d.DXEngine, please subscribe to the newsletter. If you are an existing customer, you can do this with visiting your User Account page and subscribing to changes for Ab3d.DXEngine. Otherwise you can also subscribe to newsletter on our blog

Also, please give us some feedback. You can do this by simply sending me an email to support@ab4d.com or write to a new DXEngine forum section.

 

I really hope that you are as excited about the Ab3d.DXEngine that I am. This will really bring a new era to the 3D graphics programming for business applications.

Tags:

New version of Ab3d.PowerToys gets FreeCamera and many other improvements

by abenedik 2. September 2015 18:26

I am happy to inform you that a new version of Ab3d.PowerToys has been released.

The biggest new feature of the new version is the introduction of a new camera type - FreeCamera. The FreeCamera is a camera that allows free rotation around any axis.

The first difference between FreeCamera and other cameras from Ab3d.PowerToys is that the FreeCamera is not defined by Heading, Attitude and Bank angles. Instead the camera is defined by CameraPosition, TargetPosition and UpDirection. Another difference is that the FreeCamera can be rotated freely around any axis and not only around Y axis as other cameras. This extra freedom can be useful for an experienced user. 

But you need to be careful when using the camera, because most of the users can quickly become disoriented and can struggle to align the objects correctly. With other cameras you rotate the camera as you would have your target object on the desk and you would move around the object and view it from different corners. This is the most natural way to rotate the camera. The felling of horizontal plane and up direction is preserved and you can easily navigate around. 

It is also interested that some previous versions of Autodesk products (for example 3D Studio max 2009) allowed users to rotate the camera in a similar way to what FreeCamera allows. This was allowed only with ViewCube rotation. When camera was rotated with mouse the rotation was not free but was bound to Y axis. The interesting part is that later versions (3D Studio Max 2014 and Autodesk Revit 2014) removed the free rotation with ViewCume and now ViewCube allows rotations only around fixed y axis. It looks like at Autodesk they found out that increased rotation freedom is not better for users and therefore they removed it and used the proven and more intuitive rotation around y axis.

Some users have been asking for FreeCamera for quite some time. I hope that they will be satisfied. Though I would recommend them to at least test this with their users.

 

The new version of the Ab3d.PowerToys also brings some other improvements and fixed. Many of them are related to the Ab3d.DXEngine and improve using Ab3d.PowerToys in the Ab3d.DXEngine. The Ab3d.DXEngine is a brand new DirectX 11 rendering engine that can render existing WPF 3D graphics with a super-fast and much more accurate DirectX 11 rendering engine. The engine is already available as release candidate version and can be downloaded form the Downloads page. Some additiona information about the engine can be froud on its web page. You can expect more information about the engin in the next blog post.

Here is the whole list of changes and new features:

  • Added FreeCamera - a new camera type that can be used to freely rotate the camera around without locking the rotation around y axis.
  • Fixed reading materials with ReaderObj - before a black EmissiveMaterial was added to each material.
  • Moved CameraLight and ShowCameraLight properties and StartRotate, EndRotate and all related methods from SphericalCamera to BaseCamera (this allows its usage on FreeCamera).
  • Added AutomaticallyUpdateWhenOriginalModelIsChanged to WireframeVisual3D
  • Improved WireframeVisual3D to not generate the wireframe geometry until it is added to the parent Visual3D / Viewport3D. This can prevent multiple wireframe geometry generation in the initialization phase. Also improved xml comment (for help) and sample regarding that.
  • Improved changing ShowCameraLight property at design time (before light was not always changed when the ShowCameraLight property was changed).
  • Improved using ShowCameraLight's Auto property - before when this property was set to Auto, the camera light was not shown if the scene contained AmbientLight; now camera light is added in this case (it is not added only when DirectionalLight, PointLight or SpotLight are defined).
  • Improved automatic finding of Viewport3D in BaseCamera faster and more reliable (when TargetViewport3D is not set).

Changes related to Ab3d.DXEngine:

  • Updated BaseCamera to correctly find the Viewport3D if used inside DXEngine and if TargetViewport3D or TargetViewport3DName are not set.
  • Fixed updating line color when the line color is changed after the line is already shown (when rendered with hardware accelerated in Ab3d.DXEngine).
  • Improved EventsManager3D when EventsManager3D.CustomEventsSourceElement is not set - now the default event source is DXViewportView instead of Viewport3D.
  • Improved MouseCameraController - it is not needed any more to set the EventsSourceElement to DXViewportView; now if EventsSourceElement is not set, it will be automatically set to DXViewportView.
  • Improved sending lines data to Ab3d.DXEngine (so that the lines can be created in geometry shader).

Tags:

Ab3d.PowerToys

Updated version of Ab2d.ReaderSvg published

by abenedik 21. July 2015 23:26

I am happy to inform you that I have just published a new version of Ab2d.ReaderSvg.

This version brings the following new features and improvements:

  • Added support for using polygon as clip-path.
  • Improved transforming shapes and brushes.
  • Prevented applying opacity twice - to alpha value in color and to Opacity property on element.
  • Added support for "fill-opacity" and "stroke-opacity" attributes.
  • Fixed ResourceDictionaryWriter so that the ResolveResourceKeyCallback is called also for root keys.
  • Used black as default fill color (when fill is not specified).
  • Prevented stretching geometry under some circumstances when svg file was read as geometry.

Tags: ,

ReaderSvg

Amazing new samples and features of the next major version of Ab3d.PowerToys library

by abenedik 18. June 2015 21:14

I am really happy to announce that I have just published the biggest update in the history of the AB4D Company. 

This update brings many great new features, improvements and fixes to Ab3d.PowerToys library - best library for rapid 3D application development. What is more, there are some new samples that show the power of the library. The samples can also jump start your development with providing the startup code for the standard 3D use cases.

 

Let’s start with a few screenshots of the new samples:

The following screenshot shows a sample that allows user to show the scene from different angles and with different rendering settings (in top row user can also change the layout of the scene views):

Multi scene layout with Ab3d.PowerToys library

 

The following sample shows visualization of sample data in 3D graph. The graph also supports selection of single or multiple spheres. The lower left corner of the screenshot is showing a new MouseCameraContollerInfo control that shows which mouse buttons and keyboard keys are used to rotate and move the camera:

3D graph with Ab3d.PowerToys library

 

The following image shows new ModelMoverVisual3D that simplifies moving 3D models:

Model mover to move 3D models in the 3D scene

 

And now to the list of new features:

Major new features:

  • Added LightingRigVisual3D that adds 3 DirectionalLights and one AmbientLight to the scene. The lights define the so called standard lighting rig with key, fill and back light.
  • Added TubeLinesVisual3D and TubeLinesMesh3D that can be used to create 3D lines from 3D tube objects. Those lines does not require LinesUpdater to update their geometry when camera is changed and can therefore greatly improve performance when the application is running (but require a little bit more time to initialize)
  • Added ModelMoverVisual3D that can be used to help users move 3D objects. The ModelMoverVisual3D shows 3 arrows for all three axes and allow users to move object along the axis. It can also show 3 rectangles that allow users to move the object on the plane defined by the rectangle.
  • Added support for touch events and touch manipulation events to EventManager3D (TouchEnter, TouchDown, TouchMove, TouchUp, TouchLeave; ManipulationStarted, ManipulationDelta and ManipulationCompleted) (only in .Net 4 version of the library)
  • Added MultiPolyLineVisual3D to show multiple polylines with one Visual3D – this improves performance because LinesUpdated needs to check less objects.
  • Added Ab3d.Utilities.RenderToBitmap method to render any FrameworkElement to bitmap (with support for custom size, antialasing and custom dpi setting).
  • Added RenderToBitmap to BaseCamera to render current Viewport3D to bitmap.
  • Added support for creating 3D trapezoid objects with TrapezoidVisual3D, TrapezoidUIElement3D and Ab3d.Meshes.TrapezoidMesh3D classes and with new Ab3d.Models.Model3DFactory.CreateTrapezoid and Ab3d.Meshes.TrapezoidMesh3D method
  • Added MouseCameraControllerInfo control that shows which mouse button and keyboard is required to rotate and move the camera. Also added MouseWithButtons, KeyboardKey user controls.
  • Added Ab3d.Utilities.Dump methods that can dump 3D model information into Visual Studio Immediate Window – useful for getting information about 3D objects during debugging.

 

Improvements and fixes:

Cameras:

  • Added MoveOnlyHorizontally property to MouseCameraController to restrict the camera movements to horizontal plane.
  • Added IsRotationDirectionAdjusted property to MouseCameraController. It can be used to enable adjusting camera rotation direction based on current mouse position and current attitude value. 
  • Added CameraRotateStared, CameraRotateEnded, CameraMoveStared, CameraMoveEnded events to MouseCameraController
  • Fixed calculating camera bank angle when using Ab3d.Utilities.CameraUtils.CalculateCameraAngles method.
  • Added static GetCameraMatrixes method to BaseCamera that takes Viewport3D and returns camera matrixes. Also the GetCameraMatrixes now returns Boolean instead of void - it returns false if camera matrixes cannot be calculated.
  • Fixed showing camera light after the previous Light visual was manually removed from Viewport3D.Children
  • Improved CameraLight property in Ab3d.Cameras objects. The property is used to get or set a custom light for camera’s light. In previous version under some circumstances the property's value was not set to the actual Light object that is used to illuminate the scene.
  • Added GetMousePositionOnPlane method to all cameras from Ab3d.PowerToys library
  • Added GetNormalizedHeading, GetNormalizedAttitude, GetNormalizedBank methods that return Heading, Attitude and Bank angles that between 0 and 360.

 

3D Lines:

  • Fixed updating 3D lines for WireGridVisual3D when its IsClosed property was set to true.
  • Improved LinesUpdater with adding a RegisteredLinesCount property to get number of registered lines. Also added UnregisterLine method that takes any 3D line visual from Ab3d.PowerToys.
  • Improved performance of LinesUpdater.
  • Removed memory leak from LinesUpdater - some lines that were disconnected from parent Visual3D were not disposed and were checked on each frame.
  • Improved LinesUpdater so that it did not regenerate some geometry models when the camera (or some other property) is not changed.
  • Improved rendering lines when Othographics camera is used and the lines have the same direction as the camera.
  • Fixed hiding 3D lines when IsVisible is set to false and the line is child of another ModelVisual3D

 

3D objects:

  • Improved rendering Arrow3D - before the arrow tip was rendered with a single position and that made the arrow shading too dark.
  • Changed default value for Length property on AxisVisual3D and ColorAxisVisual from 1 to 100.
  • Fixed changing DefaultMaterial on ObjModelVisual3D after the obj file has been already read. In previous version all materials were replaced by new DefaultMaterial even if obj file defined their own material and DefaultMaterial was not used.
  • Added DefaultBackMaterial to ObjModelVisual3D to specify the back material of the read models.

 

Other:

  • Added RayPlaneIntersection method to Ab3d.Utilities.MathUtils to calculate intersection of 3D ray and a plane.
  • Added ReplaceMaterial to Ab3d.Utilities.ModelUtils to replace one material with another material in a Model3D
  • Prevented freezing objects with ModelOptimizer when FreezeAll is not set to true.
  • Prevented throwing exception when MeshGeometry3D have TriangleIndices set to null in CollectModelCounters, GetDumpString and GetMeshInitializationCode methods. 
  • Improved performance of ModelOptimizer and MeshUtils.CalculateNormals
  • Added new overloads to TransparencySorter constructor, SimpleSort and SortByCameraDistance methods that also take ContainerUIElement3D as parameter.
  • Improved ModelDecoratorVisual3D when showing normal vectors on an objects that has been scaled by transformation
  • Fixed CreateFromCurvePositions method in BezierCurve - the method has thrown an exception when there were less than 6 curve points (instead of less than 2).
  • Changed return type of the HeightMapMesh3D.GetGradientColorsArray method - now the method returns array of Color value instead of array of uint values. If you still want to get array of uint values, call the new GetGradientColorsUIntArray method.

 

As mentioned before – this is the longest new features list so far. And guess what. This is not the whole list. The samples project have two additional new controls that are available with full source code:

  • AxisWireBoxVisual3D – Visual3D that shows a wireframe box with Y axis lines and values that can be used to show 3D data.
  • SceneView3D – UserControl that can show 3D models in Viewport3D and has ComboBox to specify the view angle (top, left, right, front, etc.) and a ContextMenu that specify how the 3D models are rendered (with solid model or wireframe) and what type of camera is used (perspective or orthographic). 

 

I am really excited about this new release. I hope that after checking out the new samples you will share that excitement with me.

As always, the licensed users can download their commercial version from their User Account page. Others are welcome to try the new evaluation version that can be download from our downloads page.

Tags:

Ab3d.PowerToys

New major version of 3ds file reader brings a major price reduction for the library

by abenedik 22. April 2015 09:37

This time I have one great and one even greater news for you.

The first great news is that a new major release of the best 3ds file reader (Ab3d.Reader3ds) brings some great new features to the library.

And an even greater news is that all this come with greatly reduced price. For example, the price for Ab3d.Reader3ds single developer library has been lower from $489 to only $199! Prices for Viewer3ds and for team and site developer license have been also reduced accordingly. To see the new prices, please visit our Purchase page.

 

And now to new features of the 9th major version of the library.

The library is mostly used for reading 3D models into WPF applications where the models are shown. But because of the great accuracy of importing 3ds file (in some cases the library imports 3D models even when 3D Studio Max does not import the models) the library is sometimes used as a converter to some other data format – for example to read 3D models from 3ds file and create an objective C code that defines 3D objects for iOS application. 

Such custom converter applications read 3D models from 3ds file into WPF 3D models and then convert that models into some other data format. But the problem with such approach is that some of the data is lost when converting to WPF objects. For example if 3ds file defines materials with bump and reflection map, those two textures are not available in WPF. Also when 3ds file contains animations, the animation can be played in WPF application, but you were not able to access the raw animation data.

With the new version of Ab3d.Reader3ds you are now able to get all the materials and animation key frames data that are stored in 3ds file.

 

The materials data can be get with the new Materials3ds dictionary on Reader3ds object. The key in the dictionary represents the model name. The model name is the same as in the NamedObjects dictionary (note that you can get all the names of the objects with running the DumpNamedObjects method in Visual Studio immediate window after the 3ds file has been read). The value in the Materials3ds dictionary represents a new Material3ds type. This type contains all the material data that are defined in 3ds file specification. The Material3ds type also contains a Maps list that contain all the maps (textures) used by the material. 3ds file support the following map type: DiffuseColor (the only one supported in WPF), SpecularLevel, Opacity, Bump and Reflection.

The following Class diagram shows all the fields of Material3ds and MaterialMap3ds:

Material3ds Class diagram

It may appear that there are many fields defined for materials. But compared to animation data, materials are really elementary. The Class diagram for animation data is as follows:

Reader3ds key frames data Class diagram

And that are only the classes. Each class also defines their own fields.

The key frame data can be get with calling the new GetKeyFramesData method. The method takes the model name as parameter and returns a list of BaseKeyframesTrack objects (for example PositionTracks and RotationTracks).

Each Tracks object defines their own array of Keys that define data about the object at specific time. For example PositionTracks use PositionKeys to define different positions of object at various time stamps.

To demonstrate the ability to get raw 3ds file data I have added a new sample to Reader3dsSamples project. With the sample users can drag and drop 3ds files to the sample Window and see the materials and key frames data for the 3ds file.

 

The next very interesting new feature of the new version of Reader3ds is that now it is possible to get the OptimizedMeshGeometry3D object for any 3D model read from 3ds file. The OptimizedMeshGeometry3D is a simple struct that is defined with the following code:

public struct OptimizedMeshGeometry3D
{
    public List<Point3D> Positions;
    public List<Vector3D> Normals;
    public List<Point> TextureCoordinates;
    public List<Int32> TriangleIndices;
}

As you see this is very similar to WPF’s MeshGeometry3D. The field names are the same, but the types of collections are fundamentally different. The OptimizedMeshGeometry3D uses simple Lists but MeshGeometry3D uses Point3DCollection, Vector3DCollection, PointCollection and Int32Collection.

The difference between those two types of collections is that the simple Lists are very fast when accessing individual items in the list. On the other hand the collection used in MeshGeometry3D are much more complex – on each get or set the code checks if the call is done on the correct thread, then after a few other ifs the data is get to the underlying FrugalStructList that is also not well optimized for performance.

When the Positions[i] is converted into assembly language the getter from List is converted in only a few lines of code, but in the MeshGeometry3D many lines of assembly code is executed.

This means that if you want to manipulate the 3D models with changing the individual positions, texture coordinates or other low lever data, it is much faster to change the data in a List and then regenerate the Point3DCollection from the changed list then to modify the data inside the Point3DCollection. Also if you are just reading the positions (for example to calculate the bounds), it is much faster when reading data from List then from Point3DCollection.

So, to allow using the faster lists, it is now possible to get the OptimizedMeshGeometry3D for any model read from 3ds file with the new GetOptimizedMeshGeometry3D method.

To demonstrate the performance gains, there is also a new sample in the Reader3dsSamples project.

The following are some of the results get from this sample:

Start performance tests on models with 34.403 positions and with executing each test 10 times
  Calculate bounds with MeshGeometry3D: 20,464ms
  Calculate bounds with OptimizedMeshGeometry3D: 13,779ms
  Change positions with MeshGeometry3D: 84,531ms
  Change positions with MeshGeometry without disconnecting MeshGeometry3D: 363,597ms
  Change positions with OptimizedMeshGeometry3D: 7,788ms


Start performance tests on models with 1.644.282 positions and with executing each test 10 times
  Calculate bounds with MeshGeometry3D: 1001,744ms
  Calculate bounds with OptimizedMeshGeometry3D: 669,594ms
  Change positions with MeshGeometry3D: 4191,129ms
  Change positions with MeshGeometry without disconnecting MeshGeometry3D: 11469,894ms
  Change positions with OptimizedMeshGeometry3D: 493,173ms

As you can see, calculating bounds is almost 40% faster. Changing positions (y += 10) is almost 10 times faster! And this with already optimizing the code with disconnecting MeshGeometry3D object from its parent GeometryModel3D. Without disconnecting the MeshGeometry3D object, using OptimizedMeshGeometry3D is more than 20 times faster.

To see the full test code please check the source of the sample.

 

And this is not the end of improvements.

The new version also prevents a "cross thread access" exception that could be thrown when the Reader3ds instance is created on another thread then the Read method is called.

And lastly, the new version improves animating objects when the animation does not start at first frame. In some cases the previous version wrongly positioned the objects on frames before first frame.

I hope that you like the new improvements to the Reader3ds library.

To check the new features, please download the latest trial version from the Downloads page or use your User Account page to download the latest commercial version.

Let me finish with a great news for everyone that already own a Reader3ds license, but have expired updates period: because the license renewal price is calculated based on the current price, you can now renew the Redader3ds license with greatly reduced renewal price.

Tags:

Reader3ds

New version of ReaderSvg improved support for Inkscape and adds many other new features

by abenedik 25. March 2015 20:39

I am happy to announce that the ViewerSvg (svg to xaml converter) and the ReaderSvg library have been greatly improved.

After some great customer feedback I spent some time in Inkscape. It is really a great vector drawing application with very good svg files support. The reason for checking Inkscape was that I wanted to check how custom rotate point in Inkscape is saved into svg file. The trick is that standard svg file does not support saving custom rotate point. To preserve data about custom rotate point Inkscape saves that into its custom attribute: inkscape:transform-center-x and inkscape:transform-center-y.

When drawings from svg files are shown, the custom rotate points is not important. But when the parts of the drawing are animated, the custom rotate point is very important.

Therefore I am happy to inform you that ReaderSvg has been improved so that the custom rotate center is read into the RenderTransformOrigin WPF property. This way quite tricky to implement because Inkscape saves the custom rotate center in absolute coordinates, but RenderTransformOrigin requires values to be in relative coordinates. Anyway, this works very well now.

After that improvement I have invested some additional time and added the following improvements and fixes to ReaderSvg:

  • Added possibility to set the WPF name of the objects from the Inkscape's Label (inkscape:label attribute).
  • Changed reading transformations from svg files so that the type of transformation is preserved (rotate transform is read as RotateTransform and not as MatrixTransform as before). Added new property to ReaderSvg to control this behavior: ConvertTransformationsToMatrixTransform. You can set it to true for backward compatibility.
  • Fixed reading text that is rendered with outlines.
  • Improved using viewBox attribute.
  • Improved using svg and use elements when they use clipPath, transform and viewBox.
  • Improved TrueTransform when transforming LinearGradient and RadialGradient brushes.
  • Improved support for clipping when converting shapes to geometry.
  • Added "preview Images" option to ViewerSvg. Fixing some bugs in ViewerSvg application.
  • Improved transforming object's position and size to simplify creating XAML from parts of svg file.
  • Removed setting some default values on TextBlock element: FontStyle="Normal" FontWeight="Normal" HorizontalAlignment="Center" VerticalAlignment="Bottom" (this creates cleaner XAML).
  • Improved clipping behavior with adding support for UserSpaceOnUse value in svg clipPathUnits attribute.
  • Changing the way names are set to objects when a new Canvas is created to host the object's transformation. Now the object gets the original svg name. The created transformation Canvas gets the name that has "_transform" suffix. This behavior can be controlled by SetSvgNameToParentTransformCanvas and TransformCanvasNameFormatString properties.

 

For example for the following svg file:

<rect id="rect1" x="20" y="10" transform="matrix(-1 0 0 1 0 0)" />

ReaderSvg creates the following XAML:

<Canvas Name="rect1_transform" RenderTransform="-1 0 0 1 0 0" >
    <Rectangle Name="rect1" Canvas.Left="20" Canvas.Top="10" />
</Canvas>

This way all the data from the svg file are preserved – x and y are converted into Canvas.Left and Canvas.Top, matrix transform is converted into RenderTransform.

To preserve the values we also need to create a new Canvas that contains the RenderTransform. If RenderTransform would be added to the Rectangle, than the Rectangle would be rendered at the wrong location because the Canvas.Left and Canvas.Top would not be transformed with RenderTransform matrix (Canvas position is applied after the transformation).

 

Already the most accurate svg reader has been improved. And I have also shown that the product is still actively developed. So if you find a svg file that is not imported correctly, just upload it with using the Feedback panel. 

Tags:

ReaderSvg

Improved ResourceDictionaryWriter for ReaderWmf library

by abenedik 3. February 2015 21:10

I the previous post I have described how easily is to create ResourceDictionaries from svg fils.

Today I would like to inform you that the ResourceDictionaries improvements from ReaderSvg have also come to ReaderWmf library. This means that creating ResourceDictionaries from metafiles (emf, emf) files have been greatly improved too.

What is more, the ResourceDictionaryWriter from the previous week has been further improved – now it is possible to control the number of decimals that are used in XAML. The following screenshot shows the new application:

This improvement has been also added to ResourceDictionaryWriter that comes with ReaderSvg.

After a series of improvements of 2D products I will now devote more time to 3D products again.

Tags: , , ,

ReaderWmf