##########
Draw Modes
##########

Overview
========

The HOOPS Web Viewer component supports several different ways to draw the scene, called "draw modes". Draw modes in HOOPS Visualize Web control how 3D geometry is rendered and displayed in the viewer. By changing a model's draw mode, developers can tailor the visual appearance of a scene to support different workflows such as design review, technical illustration, or assembly inspection. Rather than relying on a single rendering style, HOOPS provides multiple visualization techniques — including shaded rendering, hidden-line views, edge enhancement, and x-ray transparency — that can be applied globally or to specific parts of a model.

These rendering options are especially useful in CAD and engineering applications, where users often need to inspect internal structures, emphasize edges and features, or simplify the scene for clearer communication. The draw mode system in HOOPS Visualize Web makes it possible to combine these effects dynamically, enabling interactive and highly customizable viewing experiences.

To activate a specific draw mode, call the :js:meth:`~wv.View.setDrawMode` function on the :js:class:`~wv.View` object:

.. literalinclude:: /../../applications/client/docs/PG_Viewing_drawmodes.ts
   :start-after: //! [webviewer_setDrawModeShaded]
   :end-before: //! [webviewer_setDrawModeShaded]

The following draw modes are currently supported:

* Gooch
* HiddenLine
* Shaded
* Toon
* Wireframe
* WireframeOnShaded
* XRay

Visit the :js:data:`~wv.DrawMode` entry in our API Reference Manual for more details.

Selecting one of those draw modes renders the scene with either faces and lines turned on, faces only, or lines only. It is an easy way to turn off visibility of faces and lines for the whole model. Alternatively, you can also use the functions :js:meth:`~wv.View.setLineVisibility` and :js:meth:`~wv.View.setFaceVisibility` to control this behavior. The code below turns on wireframe mode meaning that only the lines in the model are displayed:

.. literalinclude:: /../../applications/client/docs/PG_Viewing_drawmodes.ts
   :start-after: //! [webviewer_setDrawModeWireframe]
   :end-before: //! [webviewer_setDrawModeWireframe]
   
.. image:: images/draw_modes_wireframe_on_shaded.png

*Wireframe draw mode on*


Hidden line
===========

Hidden line removal (HLR) involves displaying only visible, unobscured lines. Faces of visible geometry will be used to obscure lines the lines in the model or draw them in a dimmed style but the faces themselves will not be drawn. Typically, HLR is used to provide a result suitable for hardcopy or screenshots since having shaded facets can clutter the scene. However, sometimes end-users are also interested in seeing a model rendered with hidden line mode on the screen.

.. literalinclude:: /../../applications/client/docs/PG_Viewing_drawmodes.ts
   :start-after: //! [webviewer_setDrawModeHiddenLine]
   :end-before: //! [webviewer_setDrawModeHiddenLine]

.. image:: images/draw_modes_hidden_line.png

*Hidden line mode on*

There are various settings for hidden line mode that you can specify by retrieving and modifying the :js:meth:`HiddenLineSettings <wv.View.getHiddenLineSettings>` object. For example, in order to make the obscured lines in the hidden line render invisible you would write the following code:

.. literalinclude:: /../../applications/client/docs/PG_Viewing_drawmodes.ts
   :start-after: //! [webviewer_setDrawModeHiddenLineSettings]
   :end-before: //! [webviewer_setDrawModeHiddenLineSettings]

.. image:: images/draw_modes_hidden_line_obscured_invisible.png

*Hidden line mode on with obscured lines*


Hard edge detection
===================

A hard edge detection algorithm is enabled *by default*. This new algorithm will cause hidden line mode to look different than previous versions. A new set of functions have been added to the :js:class:`~wv.View` to control this new behavior.

* :js:meth:`~wv.View.setHardEdgesEnabled`, :js:meth:`~wv.View.getHardEdgesEnabled`
* :js:meth:`~wv.View.setHardEdgeColor`, :js:meth:`~wv.View.getHardEdgeColor`
* :js:meth:`~wv.View.setHardEdgeOpacity`, :js:meth:`~wv.View.getHardEdgeOpacity`
* :js:meth:`~wv.View.setHardEdgeThreshold`, :js:meth:`~wv.View.getHardEdgeThreshold`
* :js:meth:`~wv.View.setHardEdgeThresholdRampWidth`, :js:meth:`~wv.View.getHardEdgeThresholdRampWidth`

.. image:: images/prototype-hard-edges-on.png

*Default - hard edges on*

.. image:: images/prototype-hard-edges-off.png

*Hard edges off*


X-ray
=====

The purpose of X-ray mode is to make it easy to identify selected elements in a complex scene by turning the whole model except for the selected elements transparent. In the example below, the selected part is inside the model and would normally just be displayed as an outline. With X-ray mode, however, the selected part is fully displayed without completely hiding the rest of the model.

.. image:: images/draw_modes_x_ray.png

*X-ray mode on*

Below are the API functions to control various aspects of X-ray mode:

* :js:meth:`~wv.View.setXRayColor`
* :js:meth:`~wv.View.setXRayOpacity`
* :js:meth:`~wv.View.setXRayTransparencyMode`

As an example, let's change the opacity of the unselected lines to fully opaque:

.. literalinclude:: /../../applications/client/docs/PG_Viewing_drawmodes.ts
   :start-after: //! [webviewer_setDrawModeXRayOpacity]
   :end-before: //! [webviewer_setDrawModeXRayOpacity]

.. image:: images/draw_modes_x_ray_opacity.png

*X-ray mode on with opaque unselected lines*


Per Node Draw Mode Overrides
============================

The **Per-Node Draw Mode Overrides** feature allows you to assign custom draw modes to individual nodes within a model in each view.
Nodes with overridden draw modes render using their assigned setting, while all other nodes continue to use the view's
default draw mode.

This functionality introduces two API methods:

- :js:meth:`~wv.Model.setNodesDrawModes` — set draw mode overrides for specific nodes in the given views
- :js:meth:`~wv.Model.getNodesDrawMode` — retrieve existing node draw mode overrides for all views


Usage
-----

Use :js:meth:`~wv.Model.setNodesDrawModes` to define draw mode overrides for particular nodes, and :js:meth:`~wv.Model.getNodesDrawMode` to query
their current settings. Together, these methods provide precise control over the visual representation of individual
model components.

**setNodesDrawModes**

The :js:meth:`~wv.Model.setNodesDrawModes` function accepts a mapping of node IDs to draw modes and an array of view IDs. Each listed node will render using the
specified mode in the given views. Only **leaf nodes** that are attached to a body can have an override - if a non-leaf node is specified,
the override is automatically propagated to all descendant nodes attached to a body.
Passing an empty array of view IDs applies the overrides to all views.
Setting override to ``NoOverrideDrawMode`` will remove the override set.

.. code-block:: ts 

   const nodeId = 42;
   const drawMode = "Wireframe";
   const updateDrawModes: Record<NodeId, NodeDrawMode> = {};
   updateDrawModes[nodeId] = drawMode;
   webViewer.model.setNodesDrawModes(updateDrawModes, []);

**getNodesDrawMode**

The :js:meth:`~wv.Model.getNodesDrawMode` function accepts a list of node IDs and returns a record of node IDs mapped to their
corresponding draw modes for each view. Nodes without a body attachment are excluded from the returned results.

.. code-block:: ts 

   const nodeIds = [42, 87];
   const drawModes = webViewer.model.getNodesDrawMode(nodeIds);
   // drawModes = {42: {0: "Wireframe"}, 87: {0: "NoOverrideDrawMode"}}


Support and Constraints 
-----------------------

When using these methods, only nodes attached to a body are eligible for draw mode overrides. If a node has no body, the override will not take effect. 

.. image:: images/draw_modes_overridden_node_id.png
   :alt: Overridden node ID in wireframe view
   :align: center

*A single node rendered with an overridden wireframe mode while the rest of the model renders default*

When mixing transparent draw modes and opaques draw mode, nodes with transparent draw modes may appear in front of other geometry when these parts are inside each other. 

XRay mode is design to be render flat behinds everything. To reach correctness in depth with transparent material, use this valid workaround:

.. code-block:: ts

    // set the material of the node to transparent:
    hwv.model.setNodesOpacity([nodeId], 0.5)
    // change the view transparency mode from SingleLayer to Unsorted
    hwv.view.setTransparencyMode(TransparencyMode.Unsorted)
