Revit API Forum
Welcome to Autodesk’s Revit API Forums. Share your knowledge, ask questions, and explore popular Revit API topics.
cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Using a geometry viewer in a revit addin to preview results

22 REPLIES 22
Reply
Message 1 of 23
jesse.mom
4636 Views, 22 Replies

Using a geometry viewer in a revit addin to preview results

Hi all,

I'm trying to build a revit addin that will generate geometry in revit. In my addin, I would like to integrate an interactive 3D viewer that shows a preview of the geometry that will be generated. Basically, i'm looking for functionality such as the revit extensions offered by Autodesk, specifcally the "Wood Framing Walls" extension. In this extension, you can configure something, and see a preview of what will be generated in revit. (see attached image).

 

My question: does anyone have suggestions for open source or free 3D geometry viewers that can be included in a revit addin to preview geometry that has not yet been created in revit? Specifcally, does anyone know whether the viewer used for the revit extensions has some kind of API or is publically available somewhere( since I like the look and feel of it)?  Or is this something Autodesk can make available? The geometry to preview are simple beam shaped elements and lines, just like the example in the picture. 

 

I've found the articles by Jeremy on his building coder blog

22 REPLIES 22
Message 2 of 23
jeremytammik
in reply to: jesse.mom

Dear Jesse,

 

Thank you for your very pertinent query.

 

Implementing a decent interactive 3D viewer is certainly doable, though not completely trivial.

 

Depending on how much interaction you need with it and how closely you want to tie it in to your add-in specific workflows, a stand-alone viewer might provide an easier way to go?

 

You could use a minimal stand-alone viewer running on Windows or in your browser and hook that up to your Revit add-in.

 

Here are two untested options:

 

 

They both seem a bit too disconnected from .NET and C#, though.

 

Here are some pointers to a more .NET related resource:

 

 

Here is a detailed discussion of making use of it in WPF context:

 

 

Quite a while back, I implemented GeoSnoop, my own simple 2D polygon preview using Windows Forms:

 

 

That shows how to set up a minimal Windows form for geometric viewing, with no user interaction, no zoom, no pan, only 2D, so no orbit or anything. It might help provide a simple starting point if you wish to DIY.

 

I hope this helps.

 

I look forward to hearing how you end up resolving this.

 

Thank you!

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 3 of 23
jeremytammik
in reply to: jesse.mom

Dear Jesse,

 

Some more suggestions, from Rudi @Revitalizer Honke, translated from German for you:

 

How about using a web browser control embedded in a dockable panel or for to display the 3D model?

 

Depending on the size of the content to be displayed, you might be able to use a JS library, e.g.:

 

https://www.x3dom.org

 

You can monitor certain events to determine whether an element has been clicked.

 

If you use the MS-WebControl, there is the ObjectForScripting:

 

https://docs.microsoft.com/de-de/dotnet/api/system.windows.forms.webbrowser.objectforscripting?view=...

 

The document property provides access to the DOM, which includes X3D nodes.

 

You could also look into CEFsharp.

 

Or directly WPF3D:

 

https://www.wpftutorial.net/IntroductionTo3D.html

 

You might encounter performance problems with large models in WPF3D, especially if you don't just want to display a static view, but also rotate it smoothly etc.

 

If you do not want to display entire building models, just parts of it, e.g., a roof truss, not yet existing as a BIM element, you could build a temporary solid representation for it using GeometryCreationUtilities and extract mesh facets from that for the X3D or WPF3D IndexedFaceSets.

 

Thanks to Rudi for his suggestions!

 

I hope this helps even more.

 

I look forward to hearing how you end up resolving this.

 

Thank you!

 

Best regards,

 

Jeremy

  



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 4 of 23
jesse.mom
in reply to: jeremytammik

Thanks Jeremy and Rudi! 

 

I will look into it and keep you posted once i've got something up and running!

 

Kind regards,

Jesse

Message 5 of 23
jesse.mom
in reply to: jeremytammik

Hi Jeremy, I figured that the Helix toolkit would be a nice candidate for solving my problem. 

 

I first tried to get the viewer to work stand alone, as described in the link you've attached. This worked perfect and it displayed the sample model nicely and with smooth rotation, panning etc. 

Then I tried to create a really simple revit WPF addin with the same functionality (display a simple stl file). It works, but interacting with the viewer in my addin is really slow and laggy, while the stand alone viewer works perfectly, even with multiple revit sessions open.

 

My question: Any suggestions on how to get the same viewer performance in a revit addin as in a standalone WPF application? 

A more general question : Where do these performance differences come from? Does revit somehow throttle the resources available to the addin? 

 

I've attached both the VS projects and the sample model.stl file, so feel free to check my implementation.

 

 

Message 6 of 23
jeremytammik
in reply to: jesse.mom

Dear Jesse,

 

Congratulations on successfully implementing the two versions of the viewer, and thank you for sharing the interesting results.

 

Regarding your question on performance:

 

I see several possibly reasons for the 'laggyness'.

 

On one hand, the Revit API runs only in a single thread, no multi-threading is supported.

 

On the other hand, I have repeatedly heard of special WPF related issues interacting with Revit.

 

Maybe either or both of those aspects are affecting the responsiveness.

 

One option to resolve that issue would be to decouple the viewer from the Revit API completely, as described in the article on using IPC for disentanglement of CEFSharp from Revit:

 

https://thebuildingcoder.typepad.com/blog/2019/04/set-floor-level-and-use-ipc-for-disentanglement.ht...

  

How important is it for you to have the viewer tightly integrated with Revit?

 

Does it have to be an add-in?

 

Could you use IPC as described above to hook up the stand-alone viewer sufficiently closely with Revit to satisfy your needs?

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 7 of 23
jesse.mom
in reply to: jeremytammik

Hi Jeremy,

 

I wanted to let you know I succesfully implemented the helix toolkit wpf viewer using the suggested decoupling of processes. See attachted image. The example of IPC for disentanglement of CEFSharp was based on a windowsforms application, so I had to make some changes to make it work with a WPF Window.

 

Now that I can launch a viewer from within the revit context, and can communicate with it from my revit command/application, the next step is to get geometry from revit to the viewer. I already succesfully tested to generate an OBJ file using your OBJ exporter voor Revit 2014 (upgraded to 2018) and display it in the viewer. However, as I was reading, I found your ideas on creating an improved version of your exporter using the custom exporter framework. Is this something you already implemented, or have planned to do?

 

I will continue to make my addin work with the existing pieces of the puzzle I have so far. An improvement on the OBJ exporter would be a nice-to-have feature, but your existing exporter does the trick. Once I have cooked something up, I'm happy to share my efforts if you're interested.

 

Again briefly my use-case: I want to create an addin that lets the user generate some revit ceiling geometry, and adjust the position and composition of this ceiling interactively with some sliders and input fields in my addin. This to-be-created geometry depends on existing wall and room geometry in the revit project. As such, in my addin, I want to preview the to-be-created- ceiling geometry, in the context of the relevant revit geometry. For this I want to import some relevant revit elements into my viewer to display the context, and then display the the to-be-created geometry in that viewer as well. When the user is satisfied, he can click ok, the preview will close, and the addin will generate revit objects according to the layout and settings chosen in the viewer.

Message 8 of 23
jeremytammik
in reply to: jesse.mom

Dear Jesse,

 

Congratulations on completing this task and thank you very much for letting us know!

 

I am very glad to hear that you are able to use the OBJ viewer.

 

Here are some examples of implementing custom exporters:

 

https://thebuildingcoder.typepad.com/blog/about-the-author.html#5.1

 

It is pretty straightforward, actually.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 9 of 23
jeremytammik
in reply to: jesse.mom

Any news n this? Possibly some updated sample code to share? Another question came up today on making use of the Helix viewer with Revit... Thank you!



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 10 of 23
jesse.mom
in reply to: jeremytammik

I finally found the time to implement this. I've attached a zip file with a working solution. The solution contains 3 projects.

 

First, it contains a model viewer, which is a very basic implementation of the helix toolkit viewer, and it has the ability to view obj files. This model viewer can be used stand alone (it compiles as an exe file),  or used by a revit plugin via the Inter Process Communication route you suggested. When used stand alone, there is a hardcoded filepath in the project, change this to the obj file path of the file you want to view, debug/compile and you're good to go. 

 

second, I implemented a very basic revit OBJ exporter using the custom exporter framework. It's a combination of the XML exporter example by Arnold, and the OBJ exporter by Jeremy. It doesn't export materials or whatsoever, just meshes. This obj can both be used as a revit addin on it's own (it contains a controller class that implements the IExternalCommand) or as a library in one of your own revit plugins. 

 

Third, It contains a revit plugin the brings it all together. This plugin exports the active 3D view to an obj file using the obj exporter ( it references the obj exporter project). This obj file is saved to a hardcoded directory, and this same directory is hardcoded into the viewer project. Once the obj file is created, it modelessly starts the viewer, completely disentangled using the IPC disentanglement magic as demonstrated and implemented by Kim Sivonen.  To make this work, you have to make sure that the revit plugin points to the build-location of the exe file of you're viewer, and that it has been built.

 

To test the solution, make sure the revit plugin controller.cs file (line 98) points to the build-location of the model viewer , compile all projects, make sure the included ADDIN file for the revit plugin ends up in the right folder and points to the build-location of your project and start the plugin from a 3D view in revit 2018. 

 

Feel free to share or use this solution as a starting point for your own viewer project. 

 

Next steps (feel free to implement and share):

- support for materials

- Improve viewer controls. (zoom towards current location of the mouse (as in revit)

- implement a viewer UI for controlling the creation of additional geometry

- find a way to push back this geometry to revit.

 

@jeremytammik  Thanks for pointing me in the right directions. 

 

 

Message 11 of 23
jeremytammik
in reply to: jesse.mom

Wow, looks absolutely great!

 

Thank you very much for implementing and sharing this!

 

Would you like to create a GitHub repository for the source code, to make it easier for others to access, discuss, contribute, enhance, raise issues, etc.?

 

I will gladly promote this to a min blog post on The Building Coder to ensure it gets the visibility it deserves.

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 12 of 23
jeremytammik
in reply to: jesse.mom

Thank you once again for your impressive implementation and kind sharing. I promoted it to a main blog post for maximum exposure:

 

https://thebuildingcoder.typepad.com/blog/2019/11/integrating-the-helix-3d-viewer-with-a-wpf-add-in....

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 13 of 23

Hi,

 

Thanks for sharing this with the forum. Nice result and working very well!

 

Some last question about this topic would be how to communicate between Revit API and the external model viewer.

 

So for example you sent the Geometry of a wall to the modelviewer.(How to translate the revit geometry to helix is not the problem, but receiving it) @jeremytammik  do you have an example or could point me in the right direction where to start?

 

Thanks!

Message 14 of 23

Communicating geometry back again is not so simple, since Revit is a parametrically driven BIM modeller.

 

Hence, not geometry driven.

 

The geometry is just a view resulting from the elements, the constraints between them and their driving parameters.

 

So, you basically cannot communicate back stupid geometry. 

 

For example, for a wall, you would have to communicate back the upper and lower binding levels, the offsets from those levels, the location curve, etc.

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 15 of 23

Hi @jeremytammik ,

 

Thanks for the answer. I tried some things out to see if you only can get a simple wall to the viewer, without the need of running the viewer exe. So directly in Revit. I used as a startpoint the example from @jesse.mom  " HelixToolkitInRevitOne" and added the following code:

 

public Result Execute(ExternalCommandData data, ref string message, ElementSet elemSet)
        {           
            try
            {
                MainWindow mw = new MainWindow();

                UIApplication uiapp = data.Application;
                UIDocument uidoc = uiapp.ActiveUIDocument;
                Application app = uiapp.Application;
                Document doc = uidoc.Document;
                {
                    var meshBuilder = new MeshBuilder();

                    GeometryModel3D wall = new GeometryModel3D();

                    IList<Reference> reference = uidoc.Selection.PickObjects(ObjectType.Element, new ImportSelectionFilter(), "Select wall to convert Geometry");

                    foreach (Reference r in reference)
                    {
                        var import = doc.GetElement(r) as Wall;                   

                        Autodesk.Revit.DB.Options opt = new Options();
                        Autodesk.Revit.DB.GeometryElement geomElem = import.get_Geometry(opt);
                        foreach (GeometryObject geomObj in geomElem)
                        {
                            Solid geomSolid = geomObj as Solid;
                            if (null != geomSolid)
                            {
                                foreach (Face geomFace in geomSolid.Faces)
                                {
                                    Mesh mesh = geomFace.Triangulate();

                                    XYZ[] triangleCorners = new XYZ[3];

                                    for (int i = 0; i < mesh.NumTriangles; ++i)
                                    {
                                        MeshTriangle triangle = mesh.get_Triangle(i);

                                        triangleCorners[0] = triangle.get_Vertex(0);
                                        triangleCorners[1] = triangle.get_Vertex(1);
                                        triangleCorners[2] = triangle.get_Vertex(2);

                                        meshBuilder.AddPolygon(listPoints(triangleCorners));       
                                    }
                                }
                            }
                        }                        
                    }

                    ModelVisual3D visual = new ModelVisual3D();
                    wall.Geometry = meshBuilder.ToMesh();
                    wall.Material = new DiffuseMaterial(new SolidColorBrush(Colors.Gray));
                    wall.BackMaterial = new DiffuseMaterial(new SolidColorBrush(Colors.Gray));

                    Model3DGroup modelGroup = new Model3DGroup();
                    modelGroup.Children.Add(wall);

                    visual.Content = modelGroup;
                    mw.viewPort3d.Children.Add(visual);

                    mw.Show();
                }
            }

            catch (Exception ex)
            {
                string exMessage = "No exception message was included";
                if (ex.Message != null)
                {
                    if (ex.Message.Length > 0)
                    {
                        exMessage = ex.Message;
                    }
                }
                TaskDialog.Show("error", exMessage);
            }
            return Result.Succeeded;
        }          

        public List<Point3D> listPoints(XYZ[] p)
        {
            List<Point3D> listP = new List<Point3D>();

            foreach (XYZ points in p)
            {
                Point3D p1 = new Point3D(points.X*304.8, points.Y*304.8, points.Z*304.8);

                listP.Add(p1);
            }
            
            return listP;
        }
    }

When running this code in Revit it is running smoothly unless you zoom to close. But to come real close to the extension "Wood Framing Walls" i think this is a good starting point or you could maybe pass the geometry data to the exe version with some sort of data txt file?

 

Result running within Revit, faces are looking much nicer this way:

 

view3d.gif

Message 16 of 23

Dear Folkert,

 

Wow, that looks great!

 

And very simple, as well.

 

I definitely agree this is a brilliant starting point.

 

Why would you want to pass the geometry data to the external exe version?

 

If you really wanted to, you could either use a file or an in-memory communication channel.

 

With the geometry data in hand, you can also easily generate a useful generic file format like glTF:

 

 

Could you possibly share the entire Visual Studio solution to make it very simple for others to recompile and test?

 

Thank you!

 

Best regards,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 17 of 23

Hi Jeremy,

 

Thanks!

 

The reason i thought to sent it to the external exe version is that if someone want to zoom in really close it's more smooth. But when you dont' need that  it's working very well this way. And maybe you can change something in the settings in wpf so you can't zoom in to much. Looks like the "Wood Framing Walls " is using this technique.

 

Attached you find the zip file with the complete sollution.

 

Wow glTF is really nice, never seen that before. What would be the workflow, get geometry like i did, make a glTF of it and sent it to a WPF?

 

Message 18 of 23

Dear Folkert,

 

Thank you for the Visual Studio solution.

 

I have not done much for or with glTF, but it seems like an extremely efficient and well-thought-out format.

 

I implemented a data collector for it in the room volume glTF generator:

 

https://thebuildingcoder.typepad.com/blog/2019/06/room-volume-gltf-generator.html

 

I left the further processing and final glTF file generation to Michael Beale, though, and I don't know whether he published his results.

 

Cheers,

 

Jeremy

 



Jeremy Tammik
Developer Technical Services
Autodesk Developer Network, ADN Open
The Building Coder

Message 19 of 23

Hi,

 

Thanks, i will take a look in the world of gITF see what we can find out 🙂

 

If someone wants to implement selectable geometry in wpf, the link underneath is a good starting point

 

http://csharphelper.com/blog/2014/10/let-the-user-select-and-deselect-3d-objects-using-wpf-and-c/

Message 20 of 23

Thank you for all the examples. This is priceless!

Can't find what you're looking for? Ask the community or share your knowledge.

Post to forums  

Autodesk Customer Advisory Groups


Rail Community