New Ab3d.PowerToys and Ab3d.DXEngine with .Net 7 build

by abenedik 10. November 2022 19:58

New versions of Ab3d.PowerToys and Ab3d.DXEngine have just been released. The new versions bring many great new features and because they were released just after the .Net 7 release, the new versions also come with a new .Net 7 build.

Because this release is also linked to a new .Net version release, this blog post also shows some performance numbers related to running Ab3d.DXEngine by using different .Net versions. See the end of this blog post for more information.


Now back to new features. In the past there were many requests to improve the triangulator that was part of the Ab3d.PowerToys library. If we want to show a filled 2D shape, for example an ellipse, as a 3D object, we need to first convert 2D points to 3D points and then define the triangles that will connect the positions. This can be done by using a triangulator. The old version of Ab3d.PowerToys already has a triangulator, but it could process only simple polygons. This was improved in the new version so that the new triangulator can now process multiple polygons and also supports polygons with holes.

Triangulated 3D text

As seen from the image above, this allows generating a 3D mesh from any text (text is represented by a series of 2D shapes). The sample also shows how to generate a 3D mesh from multiple 2D shapes (ellipses, rectangles, paths with bezier curves, etc.). The lower part of the sample shows individual triangles that were generated. There is also a Slider control that can be used to show how the triangles are laid out from the first to the last.

In some cases the new triangulator can also be used instead of Boolean operations. This requires that the main 3D object has a constant height (for example represents a sheet of metal or wood). In case when user wants to subtract a cylinder or some other object that can be extruded from a 2D shape, then using the triangulator instead of a Boolean subtract operation will be much faster and will provide better results (fewer triangles will be created).

Another highly requested feature is better support for collision detection. By using bounding boxes it was already possible to do some collision detection. However, because the bounding box is only an approximation of the space occupied by the object, this was not very precise. The new version of Ab3d.DXEngine brings a new MeshCollider object that can be used to check if one 3D position is inside another 3D mesh. By checking all the positions of one mesh, it is possible to check if one mesh collides with another mesh. The new sample demonstrates that (when checking the sample use arrows, PgUp and PgDown keys):


An interesting new material type that will greatly simplify work for some users is the new FaceColorMaterial. It supports defining different colors for each of the triangles in the mesh. Before it was already possible to achieve that by using a VertexColorMaterial. But this required that the positions of the mesh were duplicated so that each triangle used its own unique set of positions. Now this is greatly simplified because the original mesh can be used. What is more, by setting the alpha color to zero, the individual triangles can be discarded from rendering. The new sample nicely demonstrates that:

Face color material

Improving the performance of the Ab3d.DXEngine is a never-ending job. This version brings two new performance improvements. The first one is for those that use DXEngine's SceneNode objects and meshes. The new version significantly improves performance of hit testing because it can use OctTree objects on DXEngine's meshes. Before OctTree objects were created only from WPF's MeshGeometry3D objects. 

OctTree object organizes the triangles in a mesh in hierarchically organized 3D space regions so that when triangles are checked if they are intersected by a 3D ray, the number of checked triangles is much much lower. This makes hit testing almost instant even on huge meshes.

Now the DXScene.DXHitTestOptions.MeshPositionsCountForOctTreeGeneration property is also used when doing hit tests on DXEngine's meshes. Its default value is 512. This means that an OctTree will be automatically generated when the mesh has more than 512 positions. You can also manually generate the OctTree by calling the CreateOctTree method.

The second performance improvement will be great news for those who are rendering many polylines (lines where line segments are connected to each other). Multiple polylines are usually defined by a single MultiPolyLineVisual3D object. But though one object is used to define multiple lines, each line was still rendered by its own DirectX draw call. And if there were thousands of lines to render, it took quite some time to issue draw calls for each line. The good news is that with the new version, all the polylines can be rendered with only one draw call. This means that there will be almost no CPU cost for rendering any number of polylines.

As always, there are also many other improvements and fixes. See the change logs for more details here: Ab3d.PowerToys changelog and Ab3d.DXEngine changelog. Also get the latest samples (Ab3d.PowerToys.Wpf.Samples and Ab3d.DXEngine.Wpf.Samples) and check for UP and NEW icons to see new or updated samples.


And as promised before, let me show you some additional performance numbers. Each .Net version brings many performance improvements. There are new classes that can be used to write faster code. But also existing .Net code can run faster because each version improves the JIT compiler so it produces faster assembler code. The following graph shows how performance of the Ab3d.DXEngine can be improved when the application is run in a newer .Net version (running in .Net 4.8 is shown with a blue rectangle that represents 100% of the time; running in .Net 6.0 and .Net 7.0 executed the code faster and therefore the rectangles are shorter):

Ab3d.DXEngine performance in .Net versions

(1) "Multi-threading and caching" sample was run with showing 20000 boxes, using no background threads and disabled DirectX caching. The DrawRenderTime performance parameter measures the time that Ab3d.DXEngine needs to issue all DirectX draw calls. This requires going through all objects, checking their state, setting the DirectX state and calling DirectX Draw method. In this sample most of the time is spent in native DirectX code so the performance gains cannot be huge. But still, there is almost 10% better rendering performance just by using a newer .Net version.

(2) "Instanced animated arrows" sample was run with showing 1 million arrows. The graph shows values for the time that is required to calculate 1 million transformation matrices - each matrix is defined so that an arrow mesh will point toward the animated sphere. The values are based on highly optimized code (manually inlined and optimized math operations) that run on multiple threads (using Parallel.For).

(3) "Instanced animated arrows" sample showing 1 million arrows but this time the source code without any manual optimization is executed. The graph shows that the new JIT compiler can greatly optimize the generated assembler and in this case can provide a 25% performance boost.

(4) "Transparency sorting performance" sample shows the performance of different sorting algorithms that sort 3D objects to prevent transparency artifacts (the sample was updated to show 7200 instead of 720 boxes). The values under (4) show the difference of sorting that sort WPF 3D objects and is implemented by TransparencySorter from Ab3d.PowerToy library. Working with WPF objects is not very fast and there will be no changes in the WPF to make this faster. So it is great news that only using a new version of .Net can significantly improve the performance.

(5) The values here are again from the "Transparency sorting performance" sample, but this time showing the performance improvements of the transparency sorting from Ab3d.DXEngine. The source code for this sorting algorithm is already highly optimized, but still newer versions of .Net can squeeze some more juice from that.

So, Microsoft, keep up the great work!


And finally, the first open beta version of the new Vulkan based cross-platform rendering engine will be available before the end of this year! Let's conclude with the new logo for the engine:

Ab3d.SharpEngine logo

Tags: , , , , , ,

Ab3d.PowerToys | DXEngine