WPF 3D and Ab3d.PowerToys Performance Tips and Tricks

by abenedik 15. January 2013 13:48

As mentioned in the previous blog post, a new "Tips and Tricks" section has been added to the Ab3d.PowerToys help file.

This section contains some basic tricks to improve performance in WPF 3D and Ab3d.PowerToys. The following is the content of the section:


Ab3d.PowerToys performance tips:

When the position or size of the 3D objects created from Ab3d.PowerToys Visual3D or UIElement3D are changed frequently (for example CenterPosition or Size of the BoxVisual3D), it is recommended to use TranslateTransform3D and ScaleTransform3D and change transformations instead. When Position or Size properties are changed, the MeshGeometry3D that defines the 3D object is regenerated. This is not good for performance and memory usage (Garbage collector will have a lot of work to recycle all unsued geometries).

For example when you need to change position of BoxVisual3D, you can change its CenterPosition property. But it is much better to define BoxVisual3D with CenterPosition at (0, 0, 0), add TranslateTransform3D to the BoxVisual3D and then change OffsetX, OffsetY or OffsetZ on the BoxVisual3D. This advice is even more important when changing more complex 3D object - for example SphereVisual3D with lots of segments.

When multiple properties are changed at once on Ab3d.PowerToys cameras or 3D objects it is recommended to call BeginInit() before applying the changes. After that call EndInit(). This will update the object just once and not after each single change.

WPF 3D does not support hardware accelerated 3D lines. Therefore Ab3d.PowerToys simulates 3D lines with creating each line from 2 triangles. To correctly show the lines, their geometry must be updated after the camera is changes. Because updating lines involves some heavy 3D calculations, this can affect performance when many lines or complex wireframe needs to be updated. It is possible to slightly improve performance with manually calling Refresh method on LinesUpdater class (see LinesStressTest sample for more info).

General WPF 3D performance tips:

Freeze 3D object that you will not modify (call Freeze method on Model3DGroup, GeometryModel3D or MeshGeometry3D). If you will change only material or transformation, you can still freeze the MeshGeometry3D.

If you want to create 3D objects on another thread (to free the UI thred), you need to Freeze the created 3D object before "passing" the result to the UI thread (see "Multithreaded Sample" from Ab3d.Reader3ds samples).

When modifying collections in MeshGeometry3D please follow the advices described in Tim Cahill's blog Optimizing 3D Collections in WPF (http://blogs.msdn.com/b/timothyc/archive/2006/08/31/734308.aspx). Two most important performance advices from that blog post are:

Initialize collections with specifying the capacity in the constructor (predefining the size to prevent resizing the collection multiple times when the items are added). For example, if you know that you will add 1000 position than instead of:

    position = new Point3DCollection();


    position = new Point3DCollection(1000);


"Disconnect" the collection before changing it:

    var positions = myMeshGeometry.Positions;
   myMeshGeometry.Positions = null; // disconnect;

   // change the positions

   myMeshGeometry.Positions = positions; // connect positions back to MeshGeometry3D