Search
  • en
  • es
  • en
    Search
    Open menu Open menu

    Introduction

    Disclaimer: PointNet has been recently renamed Typhoon; however, some of the following images still display the former, as were taken before the renaming.

    Typhoon is a tool developed by Plain Concepts for viewing, measuring and editing point clouds, Gaussian Splattings and BIM models, made with Evergine. After iterating it during the last years, we faced a need: how to allow third parties creating new features on top of Typhoon. Instead of having our single team working on the codebase, how could we allow others in an asynchronous and parallel fashion to extend its core?

    In this article we show the new architecture based on plug-ins and, how such has helped, in a real scenario, to simplify the work of different teams over a common code base.

    Typhoon

    One of its multiple features is the automatic generation of BIM files from point clouds, also known as Digital Twins. These twins empower companies by surfacing information in their buildings in a digital manner: imagine an industrial building which shows digital alerts if real components reach a limit temperature, for example. It supports the most common file types: E57, LAS/Z and PCD. It also works with PLY and SPLAT for Gaussian Splatting and IFC, the de facto standard in CAD environments.

    Development

    Why plug-ins

    Before all that, we were one year working with a codebase written in Python which, compiled into Windows EXE files, were called directly from Typhoon, in a CLI fashion. We had no better approach to mix .NET and Python worlds by that time.

    Bundling Python into executables has pros and cons. One of the worst cons was its size: we used to work with EXE files of ~2.5 GB. When you double click on it, it takes ~1 min to “uncompress” the entire Python environment and then, start executing our code. It was a pain to deal with in a daily basis. (Some time after we solved this issue thanks to the integration of CSnakes.)

    One approach we hardly considered is moving Python to the cloud, having a lightweight Web API in the middle. However, given the nature of point cloud processing, to delegate computation in the cloud is not cheap when using machines with powerful GPUs; and, occasionally, when you have an enough powerful GPU in your machine, it may be much more interesting executing such processes locally.

    Finally, we came up with plug-ins: they have the benefit of still stressing our local GPUs, but even this can be moved to the cloud and still be hidden for the final user. Where did we start from?

     

    [JF1]Esta frase no está muy bien expresada, se entiende la idea pero le daría una vuelta. Por ejemplo “delegar la computación en cloud no es barato al utilizar máquinas con GPUs muy potentes y en ocasiones cuando cuentas con un GPU suficientemente potente en local puede ser mucho más interesante poder ejecutar dichos procedimientos en local”

    IPlugIn, the entry point

    When we defined the new architecture diagram, we thought of an entry point shared by every plug-in: a simple interface which self-explains what a plug-in can do (and cannot). We named it IPlugIn and distributed it in its own package: Typhoon.PlugIns. In the end, it is a lightweight DLL .NET assembly which is the only dependency a plug-in has against Typhoon.

    Nowadays, IPlugIn allows:

    • defining the label shown under top menu bar’s Plug-Ins
    • publishing a status to Typhoon: whether it is in progress or not
    • drawing its own window (once you click on its menu item)
    • injecting its own entity in the current scene

     

    For example, a plug-in cannot add a new panel at the right side; instead, it is forced to populate its own window which Typhoon controls. We have tried, in build time, to enforce some of the requirements a plug-in has. How, then, Typhoon actually detects plug-ins?

    Installation

    Typhoon is already distributed internally with a bunch of plug-ins, all of them focused on decreasing the number of points in a point cloud (with down-sampling techniques, for instance).

    Every plug-in lives under Plug-ins folder, right at the same level as Typhoon.Windows.exe (Typhoon’s entry point). Inside, each plug-in has its own subfolder, where all of its dependencies are stored: see .NET ones, or assets (images, JSONs, etc.), for example.

    What happens if a plug-in depends on a package reference already present in Typhoon, but with a different version? We cannot load the same assembly with two different versions at the same time, at least by default. In the early days of .NET, this was accomplished through App Domains; nowadays, such has been replaced with Assembly Load Context. It is a built-in mechanism to load an assembly (DLL here) from disk and decide whether its dependencies are loaded from the companion files or from the host. This way, as we will see in the next section, plug-ins can call ImGui (the technology used to make the entire User Interface in Typhoon) and, such is shared between Typhoon and them. We pay the bill of potentially having the exact same assemblies repeated on disk (i.e. two plug-ins share dependencies); however, we consider this is not a problem in 2025 given the small sizes and cost of hardware.

    Plug-ins can also require live instances of dependencies through Dependency Injection. If a plug-in needs to work with the current point cloud, it can by simply adding IIOService to its public constructor, and Typhoon does the rest. If a plug-in wants to alert the user in any moment, it can do the same with IAlertService. Furthermore, this flats the path to unit testing, which is a common practice in our team, by leveraging a simple and decoupled architecture.

    Plug-in’s UI

    Thanks to our built-in integration with ImGui (and to our own binding as well: ImGui.Net), the entire UI has been built using just this. It has the benefits of rapid prototyping, plus the styling which allows us to give it a fresh look.

    During the different iterations, we have played with different approaches to split ImGui code into different components which communicate between them. Thanks to Evergine’s component-based model, both have fit perfectly, helping us to achieve a more maintainable software. When we decided how each plug-in could define its own UI, it was natural to stick with ImGui. We had already experience with decoupled UI components, and we imagined plug-ins in the same way.

    Typhoon is in charge of asking every plug-in which menu item they want to show under Plug-ins (at top menu bar). Once the user clicks on one of them, Typhoon directly calls IPlugIn.DrawWindow() and, what happens inside, is responsibility of the plug-in.

    Some plug-ins may have a list of inputs and a button, others a tab view with a more complex set-up. Developers have the entire ImGui’s catalog at their hands. This insanely simple approach allows to convey plug-ins’ UX from Typhoon. For example, every plug-in has a window with its name in the tittle bar, and it can be closed with the typical ‘x’ button at the right side. This way, teams can asynchronously take their own decisions on their plug-ins while all of them convey to an homogeneous solution.

    As you can appreciate, plug-ins started having a certain complexity and we needed an approach to build on solid.

    Testing

    As soon as we put in practice plug-ins, bugs started to appear here and there. One of them was as simple as crashing Typhoon because a plug-in had a ‘.’ (dot) in its name (it is a common pattern to name things with dots in .NET world). How could we reproduce it without having to manually create a new plug-in? Without manually debugging Typhoon until the crash? Avoiding regressions from now on?

    Thanks to Evergine.Mocks, we thought, we could wake plug-ins up in unit tests, and it worked! In order to reproduce the example from bellow, we simply added a new minimal plug-in (default implementation of IPlugIn, remember) and named it with a dot in the middle.

    It is easy to imagine this opened us a world of testing for before mentioned dependencies, status report, etc.

    As soon as the requirements started to grow, we took the decision of opening a door for more richer interactions.

    Entity injection

    One particular requirement we got at the beginning was highlighting an area in the point cloud. This means a plug-in can interact with the current scene in some way. “Highlighting an area” was translated into drawing a wireframed cube through Evergine’s LineBatch3D and, this inside a Drawable3D component.

    Our first approach was to enrich IPlugIn with the ability to inject a component which Typhoon would take care of. We would add such into an entity we control, thus the plug-in could just play with its component (disabling or enabling it, for instance). Although we liked it, we could fall down into having IPlugIn full of small needs, or use cases, so we moved into a broader option.

    Why not we allow plug-ins to inject entities? An entity can be as simple as having one component, and as complex as one could imagine. In the future, one plug-in may add a new point cloud format, for example. On the other side, an entity has the potential power to traverse the other entities and modify their shapes (i.e. removing components, for instance), or accessing the main camera, etc. However, we decided to trust, and adjust our implementation based on the results.

    Thanks to this approach teams can leverage their knowledge on Evergine and its component-based architecture, making plug-ins a transparent glue between Typhoon and them.

    Conclusion

    The idea of extending Typhoon through plug-ins have ended up being a practical solution. We have been working simultaneously up to three different teams (even with external companies) creating multiple plug-ins. The synchronization between all of them was significantly decreased thanks to sharing a common contract with clear specifications: the IPlugIn interface, how plug-ins are installed and show up in the UI and, how they can interact with the scene through their own entities.

    Nowadays, most of the plug-ins are developed in house; however, we would like others to create new ones as well, as soon as we make Typhoon publicly available.

    In the meantime, we continue evolving, and have in mind features as the following:

    • versioning: not only for plug-ins but, also for minimum Typhoon version required
    • plug-ins management: seeing which ones are installed, helping un/installing them
    • remote repository: why not installing them with a click, instead of doing it manually

     

    We are thrilled imaging what you may build on top of Typhoon, and which challenges we may encounter in the road.

    Marco Cobeña Morián

    Software Development Engineer