3D Viewer Usage
Introduction
3D Viewer provides a set of widgets to visualize 3D models and a set of nanoflows and Java Actions to bring in the data.
When you start from a blank app template in Mendix Studio Pro, you can follow the steps below to visualize your local 3D model quickly.
Uploading and Viewing a 3D Model in Your Browser
For the Viewer widget to visualize a 3D model, two data source attributes should be set: Model ID and Model source type. To enable uploading 3D models and visualizing them directly on the page, a set of these attributes should be returned by the Uploader widget and set to that of the Viewer widget.
The procedure shows how to configure this visualization, using a JT file as an example:
Place a Container3D widget on the page.
Put the Uploader and Viewer widgets into the Container3D widget and give them a layout.
Set a fixed height of the Viewer widget (toggle to Design mode to see the preview).
Create an entity and call it UploadedModel in your app module's domain model.
Wrap the Uploader and Viewer widgets inside a new data view widget.
Create a nanoflow, call it CreatedUploadedModel, and set this as the data source of the data view.
Create two attributes for the UploadedModel entity. Set them to receive the value returned from the Uploader's Data source and UploadModelId:

On the Data Source tab, set the data source attributes of the Viewer widget by setting Model ID to UploadedModelID and Model source type to Mendix:

On the General tab, set Automatically load parts to Yes, which enables loading the model automatically upon successful upload.
Run your app locally. You can now upload a JT file and view it directly in the browser:

Displaying Model Loading Progress with Progress Bar Widget
When the end-user is uploading or loading a model, they may want to know the uploading and loading progress. The uploading progress in the Uploader widget can seen in the uploader panel :

Loading progress in the Viewer widget can be obtained via the Progress status and Progress percentage attributes in the Events tab.
Follow these steps to display the model loading progress:
Create an entity called PageObject, add a decimal attribute called LoadingProgress with a default value of
= 0(as the Progress Bar widget expects a decimal value).Create a nanoflow called createPageObject that returns a PageObject object.
Wrap the Container3D widget with a data view and set the Data source of the data view to the createPageObject nanoflow.
Set the value of the LoadingProgress attribute by setting the Progress percentage property:

Add the Progress Bar widget to the page and set PageObject.LoadingProgress as the Progress Attribute on the Values tab.
Run your app locally. You can see the real-time model loading progress:

Previewing Models Without Uploading
To preview a model directly without uploading to Mendix file storage, drag and drop the file into the Viewer. If you want to upload the model after the preview, just click the Upload to Mendix File Storage icon on the upper-left corner of the Viewer.

Utilizing More 3D Functionality
You can add more 3D widgets to the page to enable more 3D functionalities and arrange the layout of them as needed. For example:

Managing Uploaded Models
In previous use case, you can only visualize the model you upload.
Usually, you will also need to manage the models that are uploaded and stored in the data storage. 3D Viewer provides the GetModelListFromMendix nanoflow and DeleteModelFromMendix microflow to help you build model data management functionality into your app.
Building a Model List
The Mendix native list view can be used to display the model list by following these steps:
Use the View3D/USE_ME/GetModelListFromMendix nanoflow or copy it to your app module. A list of ModelDocument objects will be returned after calling the nanoflow.
Add a pop-up page to display the model list via a button click or another event of your choice.
Place a list view in the page and set the GetModelListFromMendix nanoflow as the Data source.
As GetModelListFromMendix requires a Pagination parameter input, wrap the list view with a data view. Then, create a nanoflow called CreatePaginationObject nanoflow and set that nanoflow as the list view's Data source.
Fill in the list item with the information you are interested in:

Opening a Model from the Model List
Once you have the model list, you may want to click to select a model from the list and view the model. As the Viewer widget expects ModelId and Model Source Type to visualize a model, such information of the selected model needs to be passed to the Viewer widget. Since each list item is a ModelDocument object and this object contains various pieces of information about the selected model (including ModelId and Model Source Type), you need to pass this object to the Viewer widget.
Follow these steps for configuration:
Define the On click action for the list view to pass the selected model to the Viewer widget that is present in another page (so the selected model can be loaded into the viewer). An example approach is to create an entity that is associated with the ModelDocument entity defined in the Viewer3D module's domain model. Make the object a shared object between the page the Viewer is in and the model list page. In this example, you are creating a PageObject with this home page:

This is the model pop-up page:

Set the On click action of the model list item, then change the ModelDocument object with which the PageObject is associated to return the value so that home page can be refreshed on a PageObject change:

Run your app locally. You will get a simple model list where you can select which model to open and visualize it with the home-page viewer:

Deleting a Model
There might be some models that you do not want in the database, so you can delete these, too. The 3D Viewer app service provides the DeleteModelFromMendix microflow to achieve this.
Follow these steps to delete a model from the database:
Use the Viewer3D/USE_ME/DeleteModelFromMendix microflow directly or copy it to one of your app modules.
DeleteModelFromMendix expects a ModelDocument (which represents a model stored in Mendix file storage) as an input parameter. After successful execution, the model will be deleted from Mendix file storage. In the previous steps, a model list was built, each list item of which is a ModelDocument. For a model list item, add a Delete button.
Create a nanoflow called DeleteModel and set ModelDocument as the input parameter. Then, call the DeleteModelFromMendix microflow and commit the ModelDocument:

Set the On click event of the Delete button to the DeleteModel nanoflow.
Run your app locally. You should be able to delete a model by clicking Delete.
Now you are able to get a list of models, select a list item to open a model, and delete the model.
Handling Viewer Events
Multiple events can be picked up by the Viewer widget and can be used to build your customized event handling logic.
There are four main types of events that can be picked up on the Viewer widget, which are described in the sections below.
On Selection Change
By selecting one attribute to set Selection, you can get information on the selected part (for this you might need to work with Viewer APIs; if you have inquiries on how to use the Viewer APIs, please contact Siemens Support).
Selection takes a String attribute. You can define an attribute and bind that attribute to Selection property. In a running app, when user select on a model part, the selection event will be triggered, and the selected part info will be populated to this Selection attribute. You can easily get this selected object information (psid and viewer)and use it in the actions.

Like other Mendix events, you can select from a list of actions upon a model part selection for Action. One possible use case is utilizing GET APIs exposed by the Viewer (for example, get Boundingbox by PSID, set the material by PSID in a JavaScript action, include this in a nanoflow, and set the Action to call this nanoflow).

On Error
By selecting one attribute to set the Error event, you can pick up an error exposed by the Viewer.
Error takes a String attribute. You can define an attribute and bind that attribute to this property. In a running app, when there's problem visualizing a model, the error event will be triggered, and the error information will be populated to this Error attribute. You can easily obtain this error message raised by viewer and add custom actions to trigger when error arises.

Like other Mendix events, you can select from a list of actions upon a Viewer error for Action. One possible use case is show a error pop-up page to let user know the error details.

On Progress Change
By selecting one attribute for the Progress status value, you can get the current loading status and the loading percentage of the model, product structure tree, and PMI tree.
Progress status takes a String attribute. You can define an attribute and bind that attribute to this property. In a running app, upon loading a model, product structure tree, PMI tree, and PMI shape, the load progress status information will be populated to this attribute. You can easily get this model loading status information (Notloaded, Loading, Loaded)and use it in the actions.
Progress percentage takes a Decimal attribute. You can define an attribute and bind that attribute to this property. In a running app, upon loading a model, product structure tree, PMI tree, and PMI shape, the load progress percentage information will be populated to this attribute.You can easily get this loading percentage and use it in the actions.

Like other Mendix events, you can select from a list of actions upon progress change for Action. One possible use case is use a progress bar widget to display captured model loading percentage to user.

For more information, see Displaying Model Loading Progress with Progress Bar Widget.
On Load
By selecting one attribute for the Loaded value, you can get the current loading status of the product structure tree.
OnLoad takes a Boolean type attribute. You can define an attribute and bind that attribute to this property. In a running app, when you open a model, product structure tree will need to be loaded first, the product structure tree load event will be triggered, and the product structure load information will be populated to this attribute. You can get the current loading status of product structure tree and use it in the actions.

Like other Mendix events, you can select from a list of actions upon the product structure tree loaded status for Action. In order to call the On Load action, you must bind a valid Loaded value. One possible use case is show a pop-up page to let user know if product structure is successfully loaded.

Creating a 3D Section
When a model is loaded in the viewer, the Section View widget enables the following:
- Inspecting the interior structure of a model by adding standard section planes
- Deleting a section plane
- Clearing all section planes
- Clipping away parts
- Positioning a plane
The sections below present operations within the Section View widget.

Action
- Add – Use this to add a section plane. First, select the axis along which you would like to section the model, then click Add. You will see a section plane of the desired axis added to the scene. The default position of the newly added section plane is in the middle of the bounding box of the direction selected.
- Delete – Use this to delete a selected section plane. Click the edge of the section plane to select it (when selected, the section plane edges are highlighted in yellow color). Then, click Delete.
- Clear – Use this to clear all the section planes added to the scene.
Direction
- X Direction – sets the X axis of the default coordinate system as the reference
- Y Direction – sets the Y axis of the default coordinate system as the reference
- Z Direction – sets the Z axis of the default coordinate system as the reference
For example, if you select Y Direction, then the cross section is created on the ZX plane.
Clipping
When a section plane is selected (and highlighted in yellow), you can choose which part of the model you would like to clip away by selecting a clipping option:
- Off – do not clip
- Both – clip both sides, showing the 2D intersecting curve on the section plane
- Near – clip away the positive side (toward the Direction)
- Far – clip away the negative side (away from the Direction)
Position
You can move the position sliders to adjust the position of the section plane along its axis. You can also type in an exact position to place the section plane at an exact position.
You can add multiple section planes to cut the model in different directions. After the section, you can save a snapshot of a section view. You can also add markup annotations on the section view and save them for later review.
SectionManipulator
An advanced end-user can enable the SectionManipulator to move / rotate the section plane using advanced configuration. There are two flavors as illustrated below:
| enable SectionManipulator | enable SectionHandle |
|---|---|
![]() | ![]() |
Performing 3D Measurements
When a model is loaded into the viewer, the Measurement widget provides a set of tools to measure different geometrical entities:

The sections below describe these tools.
Measurement Mode
- Distance – measure the distance between two part features
- Length – measure the length of a line
- Radius – measure the radius of a circular edge or surface
- Angle – measure the angle between two edges or surfaces
- Area – measure the area of a surface
Action
- Delete – select one measurement result, then click Delete and the selected measurement result will be removed from the scene
- Clear – clear all the measurement results in the scene
Setting Preferences
You can change the settings of the Preference widget to customize the behavior of the model and set it up to suit your needs.

Click Preference to display the dialog. You can set your filter as a preference in any combination you like, and when you click the OK button, the filter will take effect the next time you open a file; the Reset button clears all settings. This method can only set the preference when your application is running, but we also provide a more advanced method - before the application starts - to set your preference. For details, refer to Advanced Configuration.

