Major new version of Ab3d.PowerToys and Ab3d.DXEngine published

by abenedik 19. December 2025 16:36

I would like to inform you that I have just published a major new version of Ab3d.PowerToys and TWO new versions of Ab3d.DXEngine. One new Ab3d.DXEngine has version 7.2, and the other has version 8.0.

Both v7.2 and v8.0 of Ab3d.DXEngine versions have the same features, but version 8.0 introduces breaking changes because it no longer requires the SharpDX library. Instead, it defines all the required DirectX 11 interop inside the library. Because the new interop structs and classes have new namespaces, this requires some changes in the code that uses the library. But if you just want to use the new features without changing your code, you can upgrade to version 7.2.

But before I describe the differences between those two versions in more detail, let me quickly mention some other major new features. This time, the Ab3d.PowerToys got more major new features. Here is a quick list:

  • Added camera rotation, movement and zoom smoothing to MouseCameraController.
  • Improved model slicing by adding support to close the sliced models.
  • Improved BezierCurve and BSpline classes by adding methods that use an adaptive algorithm that generates the curve position based on angle change.

The following are two additional major improvements for the new Ab3d.DXEngine library:

  • Improved ID bitmap performance by reading only part of the rendered ID bitmap from the GPU memory.
  • Added Points3DTo2D methods to DXScene that can calculate 2D screen positions much faster than the same method from Ab3d.PowerToys library.

 

After the overview, let me now continue with the details about the DXEngine without the SharpDX library.

First, let me explain why I'm providing a special version without the SharpDX library.

Because the SharpDX project has not been actively developed for quite some time (the last NuGet package was published in 2018), some of my customers have expressed concern about the library.

In my opinion, the SharpDX code is one of the best-written .NET libraries. Also, the DirectX 11 API is no longer changing, so the existing code does not require any additional changes. What is more, because SharpDX used clever IL rewrites, the DirectX interop calls are as fast as if newer unmanaged function pointers were used.

On the other hand, some of the structs that are defined in the SharpDX library, like Vector3 and Matrix, now have similar structs in System.Numerics namespace that is part of the .Net. Because the new structs are highly optimized to use new SIMD and vector instructions, they can be significantly faster than using the structs from SharpDX. For example, my benchmarks (using BenchmarkDotNet) show that the matrix multiplication is around 4 times faster when using Matrix4x4 from System.Numerics instead of Matrix from SharpDX. Also, the Points3DTo2D method that calculates 2D screen positions from an array of 3D positions is almost twice as fast when using System.Numerics. But on the other hand, most other methods and all DirectX 11 API calls are not significantly faster. Therefore, if you are not doing a lot of Vector3 and Matrix calculations, you should not expect bigger performance improvements. Anyway, if you decide to use the new version 8.0, then please use the Guide to upgrade to v8.0.

Also note that Ab3d.DXEngine does not define all the DirectX 11, Direct3D, and DXGI classes and functions (only the functions actually used by Ab3d.DXEngine are defined). If you use your own low-level code that communicates with DirectX 11, and you require some functions that are not defined in the new Ab3d.DXEngine, then you may still need to use SharpDX or some other library (like Vortice.Direct3D11). However, if you are missing just one or a few functions, please send me an email with the list of missing interop functions, and I may add them to Ab3d.DXEngine.

Another important note about version 8.0 is that it requires .Net 10. This is needed to define instance extension methods so that even though the structs from the System.Numerics namespace do not define the same methods as structs from SharpDX, the new extensions allow defining all the required methods from SharpDX. For example, SharpDX.Matrix defines the Transpose method that does not exist in the System.Numerics.Matrix4x4. The new extensions support in C# 14 allows us to define the missing instance Transpose method in the Matrix4x4 struct. Without that, we would need to use many #if and #endif statements with different code paths.

If you can use .Net 10 and you are willing to make some changes to your code, then it is recommended to switch to v8.0 instead of v7.2. This will also make your app start a little bit faster because it will not need to read 4 SharpDX assemblies.

But you can still stay on v7.2. In the future, the new versions will maintain this duality (by releasing v7.3 and 8.1, etc.).

 

And now to other new features. I am very happy that I was able to provide the three mentioned features to the Ab3d.PowerToys library. They have been on my todo list for quite a while and were also requested by some of the customers.

I always say that intuitive and efficient camera controls are the heart of every 3D application. They are the main interface between the 3D scene and the user. In this regard, I am very happy to inform you that a new version provides support for smooth camera rotation, movement, and zooming. Before, when the user rotated the camera with the mouse, it rotated immediately. But in nature, things rarely move that rapidly and usually have an inertia that smooths their movement. Also, before, when the user zoomed the camera by using the mouse wheel, the camera’s distance was changed immediately - it looked like the camera jumped from one position to another. Now, rotation, movement and zooming can be animated nicely. To preserve backward compatibility, the smoothing is disabled by default. But it can be very easily enabled by setting the CameraSmoothing property on MouseCameraController to Slow, Normal or Fast (it is also possible to fine-tune the settings).

The following screenshot shows the new sample that demonstrates the camera smoothing (see the darker green line that smooths the Heading changes - represented by light green color).

Camera smoothing in Ab3d.PowerToys

For a more detailed demonstration, see the Camera smoothing video.

I would encourage you to try the new smoothing for a few days. After using that for a few days, I must say I now find the old “immediate camera mode” very unnatural. Therefore, I am sure that by adding only a single line of code to enable camera smoothing, you will give your users a subtle but substantially better user experience.

 

Another interesting feature that has been a part of Ab3d.PowerToys for a very long time is slicing 3D meshes and models. This allows any 3D mesh or model to be sliced by a 3D plane. But after slicing, you could always see inside the sliced models. But with the new version, you can now close the sliced models. You can also create a single 3D mesh that represents the slice (a planar mesh that represents the 3D plane inside the mesh).

What is more, the slice code has been moved from the Plane struct to the new Slicer class. This cleans the Plane structs by removing the temporary collection from the struct, leaving Plane with only the data required to define the 3D plane. 

See the screenshot from the new Slicer sample:

New mesh slicing sample in Ab3d.PowerToys

Closing sliced mesh

And as before, here is a short video from the slicer sample.

 

The last interesting new feature from the Ab3d.PowerToys is improved support for generating Bezier and BSpline curves. Before, you specified a fixed number of positions per segment that always generated the same number of positions between two curve segments. This is very fast to compute, but can generate too many points along nearly straight sections and too few where the curve bends sharply.

With the new version, the curve positions can also be generated by using an adaptive algorithm. It adds more points where the curvature is higher. This takes longer to compute, but generates smoother curves with fewer positions.

The following screenshot shows the new angle-based adaptive algorithm in action:

Bezier curves with angle based positions generation

You can compare that with the fixed points-per-segment method (this generates 91 positions but has worse accuracy than 56 positions of the angle-based method):

Bezier curves with fixed position generation

 

The Ab3d.DXEngine got two new features that can significantly improve performance in some of the use cases.

The first is great when using the ID bitmap for hit testing. Standard hit testing is done by creating a 3D ray and checking whether it intersects any triangles in the mesh (before checking all triangles, the mesh's bounding box is checked for ray intersection). When there are a lot of objects in the 3D scene or when the meshes have a lot of triangles, the hit testing code may need to execute millions of ray-to-triangle intersection tests. For large meshes, the DXEngine can also use OctTrees, which can significantly reduce the number of tests, but this can still be an expensive CPU operation.

An alternative to the standard hit testing is to render the 3D scene to a bitmap, but instead of using the usual materials, the objects are rendered with colors that are generated from their IDs. This way, it is possible to get the object ID from the color on the rendered bitmap. In some cases, this can work much faster.

But when the application’s window is large (for example, 4k), it takes a significant amount of time to copy the rendered bitmap from GPU memory to CPU memory. The new version can solve that problem by preserving the rendered bitmap in GPU memory and copying only a small portion of it to CPU memory. This can be much faster.

See the updated VertexIdBitmapHitTesting and InstancedIdBitmapHitTesting samples on how to use this new feature.

 

Another performance improvement in DXEngine is a new way to calculate 2D screen positions from a list of 3D positions. To achieve that, you can use the Points3DTo2D method on the Ab3d.PowerToys’s camera object. The method takes an array of Point3D items and fills another array of Point items with 2D screen coordinates. As with most of the operations in WPF, those calculations are done by using double precision (using Point3D and Matrix3D). But with DXEngine, you can also use optimized Vector3 to represent a 3D position. This uses float values and can be further optimized by using SMID and vector operations.

So, if you need to calculate 2D screen positions, the new version of Ab3d.DXEngine provides a new Points3DTo2D method on the DXScene object. This method takes an array of Vector3 items instead of an array of Point3D items. Because the new method uses float values, the code in v7.2 is 10 times faster than the same method from Ab3d.PowerToys library (and 20 times faster when using v8.0 without SharpDX). For example, calculating 10,000 screen positions takes around 0.34 ms when using the camera’s Points3DTo2D method. When using this method on the DXScene withAb3d.DXEngine v7.2 that operation takes 0.035 ms and when using v8.0 it takes 0.0173 ms. Note that if you need to convert only a few positions, then you can use either method (depending on whether you use Point3D or Vector3).

As always, there are also many other smaller improvements and fixes. See the Ab3d.PowerToys change log and Ab3d.DXEngine change log.

 

Until now the Ab3d.PowerToys and Ab3d.DXEngine libraries have been distributed by using NuGet packages and also by using the commercial version installer (msi file downloaded from the User Account web page). Because this requires maintaining two different versions of the library and two different sample projects, and because I am not going to renew the recently expired Microsoft code signing certificate that was used to sign the msi installer, I have decided that this version is the last version that is distributed by both methods. This means that future versions will be distributed only by NuGet packages. Therefore, if you are still using the commercial installer, I would encourage you to migrate to the NuGet package distribution.

 

In this version, I also wanted to publish a new Assimp importer. The native Assimp library has been updated to version 6.0.2, but this introduces some breaking changes when reading animation data. Therefore, the newly released version still uses Assimp v5.4.2. Anway, if you are using Assimp importer and do not require animation data, then you can still get the native binaries from the Assimp releases. After extracting the zip with binaries, rename the native dlls into Assimp64.dll or Assimp32.dll and copy the new version of those two files over the previous version. I will try to update the AssimpNet project to support new animation data structures in the following days. Then I will update the samples. So if you are interested in getting a new Assimp version with animation support, check the samples in the coming days.

 

This year, I also planned to release the first official version of the Ab4d.SharpEngine for the browser. But this has to be moved to January.

Also, the development version for the desktop and mobile Ab4d.SharpEngine library already has a ton of new features, including support for Physically Based Rendering (PBR) materials. I am planning to release this version in February.

 

And now, the only thing that is left for me is to wish you happy and peaceful holidays and all the best in the new year.

Tags: , , ,

Ab3d.PowerToys | DXEngine