##########
Overview
##########

The **Visualization Streamer** (*VizStreamer* for short) is a component in |ProductName| tailored towards 
showing CAE visualizations in a web application with data pushed from an application/service running on the server 
side. It consists of several parts:

- **VizStreamer Service** - A server application with a gRPC interface capable of receiving CAE display data and 
  streaming it to the *Stream Model* client model.

- **VizStreamer Proxy** - A C++ proxy (header files + static lib) to make it easy to send data from a C++ application 
  to the *VizStreamer Service*.
  
- **Stream Model** - A |ProductName| client-side model capable of rendering the 3D models sent from the 
  *VizStreamer Service*.

************************
Overall design
************************

.. image:: /images/VizStreamerDesign.png
   :alt: Visualization Streamer Design

************************
Data Objects
************************

The service supports the following data:

- **Indexed Polygon Meshes** - A group of surfaces (polygons or lines) where you provide the vertices (3d coordinates) 
  and specify polygons with indices referencing these vertices. Any number of vertices per polygon is supported, but 
  the polygons must be convex for proper rendering. There is an optimized method for a *Mesh* where all the polygons 
  have the same number of vertices.

- **Mesh Scalar Results** - Scalar results that will be shown on a mesh. Per vertex, per polygon and per polygon-vertex 
  mappings are supported. This is useful for mapping scalars onto a mesh and using the built-in result mapping features 
  of |ProductName|. 

- **Mesh Vector Results** - Vector results that will be shown as vector arrows attached to a mesh. Per vertex, per 
  polygon and per polygon-vertex mappings are supported. You can show any number of vectors on a given mesh.

- **Mesh Displacement Results** - Displacement of the vertices in a mesh. Useful for showing animations where a mesh is 
  deformed, but not remeshed. It is more optimal as the topology of the mesh does not need to be redefined, only the 
  displacement of the vertices.

- **Point Cloud** - A set of points rendered as points or vectors (if available). It can be used to show a set of 
  vectors as you can attach a vector result to the points in the point cloud. This is useful for showing vectors that 
  are independent of a mesh, e.g. regular sampled vectors on a cutting plane.

- **Particle traces** - You can specify a set of points and their time stamp to be visualized as a 
  particle trace / streamline in the web client. The particle traces can be visualized and animated as spheres, comets 
  and cylinders.

- **Textures** - You can specify a texture image and then provide per-vertex texture coordinates for each vertex in a 
  mesh. This allows for custom texture mapping, e.g. custom scalar mapping on a mesh, or textures for more realistic 
  visualization.

- **Transforms** - You can push an array of 4x4 transformation matrices and then reference this when specifying the 
  MeshInstance. This allows for rigid body animation with minimal overhead.

- **Settings** - You can provide settings for Meshes, Point Clouds, Scalars, Vectors and Particle Traces. These 
  settings specify how the various data will be rendered in the web client.

All these types of data are pushed to the service via ``pushXX()`` calls (e.g. ``pushIndexedPolygonMesh()`` (C++) or 
``VizStreamerService.PushIndexedPolygonMesh`` (gRPC)). The calls will return a ``ResourceKey``, which identifies the 
data and is used to reference the data when building up the visualization (*Frame*\(s)) that will be rendered in the 
web client.

.. note::
   The data objects are **immutable** (i.e. they cannot change). Any modifications of data will require pushing a new 
   data object.

************************
Instances
************************

Instances bind data and settings and, by that, define how to render the data. These instances/groups are then 
referenced in *Frame*\(s) to build the scene.

There are 3 types of instances:
 
- **MeshInstance** - A mesh instance binds a *Mesh* (see *Indexed Polygon Meshes* above) with the settings for how to 
  render the mesh. You can also bind a scalar, vector or displacement results, as well as textures/texture coordinates 
  and transformation matrices.
 
- **PointCloudInstance** - A point cloud instance binds a *PointCloud* data object to a settings object that defines 
  how to render it. It also includes optional fields for specifying scalar and vector results that are visualized on the 
  point cloud.

- **Particle Traces** - Binds the particle trace data with the settings on how to visualize the particle traces. 

************************
Frames
************************

A *Frame* defines all the instances/groups that should be shown in the *Stream Model* at any given time. A *Frame* is 
defined by an array of ``ResourceKey`` of all the mesh instances, all the point cloud instances and all the particle 
trace instances that should be rendered.

``createFrame()`` is a server-side **barrier**, meaning the call will not return until the model is processed 
(spatially partitioned, compressed and prepared for progressive streaming) and ready to be streamed to any client 
subscribing to the stream. Note: The call will return before the model is shown in the client. 

When a frame is published to the *VizStreamer Service* it will be shown in the model subscribing to the given stream 
(see Streams below for more info). This is done with ``publishFrames()`` (C++) or ``VizStreamerService.PublishFrames`` 
(gRPC). The Frames are already processed (as ``createFrame`` is a server-side barrier) so this just tells the client 
models to show the given Frame(s). The client will then fetch any data not already in the client and progressively 
update the rendering until it is complete. Calling ``publishFrames()`` will replace any previously published *Frames*, 
so you need to include all *Frames* that should be shown.

************************
Streams
************************

Streams allow multiple setups/cases/configurations in one Visualization Streamer Service instance. You will need at 
least one stream to use the service. A web client *StreamModel* is always attached to (subscribes to) a *Stream* within 
a given *VizStreamer Service* instance.

A *Frame* is always attached to one *Stream*. However, all other data items (*Data Objects*, *Instances*) can be shared 
between streams (you do not push data to a stream). If two streams are sharing data, the data will only be streamed 
once to the web client.

Streams are useful for visualizing more than one model/setup/configuration at a given time. It can be used to compare 
two designs, show the model with two different results, etc.

************************
gRPC documentation
************************

The interface to the *Visualization Streamer Service* is implemented with *gRPC*. You can find the detailed gRPC 
documentation in :doc:`grpc`.

************************
C++ Proxy documentation
************************

For easy use in a C++ application, we have created a C++ proxy for the gRPC service. See the documentation in 
:doc:`proxy` for more details.