It is sometimes desirable to “spruce” up a model with more interesting materials that don’t already exist in the original CAD file. With HOOPS Communicator now supporting PBR it is fairly easy for example to give a surface a realistic looking metallic appearance while keeping its original color.
This tool makes it easy to group entities together and assign them a specific material. It then allows the user to export this new material file and use this data the next time the model is loaded.
The code is largely based on the SelectionBasket class and has similar functionality when it comes to grouping entities and displaying the various groups.
Usage Tips:
-
The best way to use this tool with the default UI is to create various groups of entities you want to apply different materials to by selecting the relevant nodes and then pressing the “Add” button. This will create a new entity group in the Material Tool table. Initially this entity group has no material set. You can then assign individual material properties directly from the table rows using the various buttons and sliders. (color, opacity, metallic, roughness). The button on the very right unsets all material settings for that group. If more than one entity is in a group you can open that group and set the material attributes for individual entities which will override the values of the parent. Each group can only contain a node once so if you are defining a new group with an already existing node it will be removed from the original group and placed into this new group.
-
One way to quickly assign an attribute to the whole model (e.g. give the whole model a metallic appearance) is to add a group containing just the top level node of a model. You can then apply a material common to all nodes but still specify material settings for individual child nodes in other groups. You just have to keep the node order in mind as all material information will be applied together whenever a material change is made and HOOPS Communicator has no concept of material inheritance. For example, if you set a metallic factor on the root node and you want to override that value in other material groups you will have to make sure the root node group is defined before the other groups. You can drag a row around in the table if that is not the case.
-
If you set the opacity value of a node to 0 the material tool will turn “off” its visibility (meaning it can’t be selected and is not considered during rendering). This is an easy way to quickly hide parts of a model.
-
This tool works great in combination with the Model Tree Search class you can also download from the forum to quickly find groups of nodes that should share a common material. We have updated the search class to now include the ability to also search by original part color.
-
By default the name of a material group is taken from the name(s) of the nodes in that group but you can specify your own name by directly editing the cell in the table.
-
You can define multiple Material Groups Baskets each containing a complete different set of material groups for a given model. You can then decide which one to apply when a model is loaded with the switchBasket() function (see below).
-
One limitation of setting materials using this class when the model is initially loaded is the fact that the original materials of the model will briefly appear because applying the new materials can only be done after the modelstructureready callback has triggered. As a workaround you can pause rendering ( hwv.pauseRendering() ) in the sceneReady callback and then resume it again ( hwv.resumeRendering() ) after calling the refresh function in the code below.
-
After you are done with creating your desired material groups you can then export the group definitions either via the API or using the export button which will download a file called “materialdef.json” to the clients computer. To use this file when loading the model again simply add the code below which will run the Material Tool without its UI and apply the defined materials (make sure to wait until the modelStructureReady callback has triggered):
res = await fetch('data/material1.json');
let json = await res.json();
myMaterialTool = new MaterialTool(hwv);
myMaterialTool.fromJson(json);
//You can optionally switch to a different Material Tool Basket (default is 0)
//if the file contains more than one set of material definitions.
//myMaterialTool.switchBasket(1);
myMaterialTool.refresh();
API
myMaterialTool = new MaterialTool(hwv);
Creates a new MaterialTool object. The constructor should be called after the model is initialized (e.g. after the modelstructureready callback has fired).
myMaterialTool.initializeUI("materialtooldiv", true);
Initializes the UI for the Material Tool. The first parameter is the id of the div that the Material Tool will be using. The second parameter indicates if the default buttons should be shown. If this parameter is set to false you need to provide your own UI to interact with the table.
myMaterialTool.refresh()
Reapplies all materials
myMaterialTool. setDisallowBodyNodes(true)
If set to true than body nodes can’t be selected in the viewer (the viewer will select the parent part instead). Defaults to true.
The functions below are only relevant if you are implementing your own UI on top of the material table
myMaterialTool.export()
Exports the content of the Material Tool to a local file.
myMaterialTool.toJson()
Generates a JSON object of the content of the material tool.
myMaterialTool.fromJson(content)
Populates the Material Tool from the provided JSON object.
let newbasketid = myMaterialTool.addBasket()
Adds a new Material Basket and switches to it.
myMaterialTool.switchBasket(basketid)
Switches to a different basket based on its id.
let activeBasketId = myMaterialTool.deleteCurrentBasket()
Deletes the currently active basket.
let count= myMaterialTool.getBasketCount()
Returns number of material baskets.
myMaterialTool.addNodesFromSelection()
Adds all nodes currently selected in the viewer to the currently active Material basket.
myMaterialTool.addNodes(nodeids)
Adds a list of nodeids to the currently active Material Basket.
myMaterialTool.removeSelectedNodes()
Removes all nodes currently selected in the viewer from the currently active Material basket.
myMaterialTool.removeNodes(nodeids)
Removes a list of nodeids from the currently active Material Basket.
Below is the code for the Material Tool class. Besides the standard HOOPS Communicator libraries and jQuery it uses tabulator to display the material table. To include tabulator from a CDN add the following to your html:
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/tabulator/5.0.7/js/tabulator.min.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/tabulator/5.0.7/css/tabulator.min.css" rel="stylesheet">
It is important to note that this code is not production-ready and provided “as-is”. It is really meant as a starting point for your own development and as an example of some of the functionality and concepts used in HOOPS Communicator.
If you have any questions or comments, found a bug or have suggestions for additional features or improvements, please don’t hesitate to post about it here in the forum.
MaterialTool.js (29.7 KB)