:tocdepth: 2

#######################################
vsp::VizStreamerProxy - C++ Proxy Class
#######################################

The *VizStreamerProxy* class is a C++ interface that sends visualization data to the |ProductName| 
*Visualization Streamer Service* backend. It simplifies usage by hiding the lower-level gRPC calls behind user-friendly 
C++ methods. 

The *VizStreamerProxy* class defines a pure virtual interface to the proxy. It is defined in the *vsp* namespace. 

We provide a `vsp::grpc_impl::VizStreamerProxyGrpc` class implementing this interface for a gRPC connection. After 
creating the object, use the `connectToService()` method to connect to the *Visualization Streamer Service*. After a 
successful connection, the proxy is ready to use.

.. code-block:: cpp

    const std::string serverAddress = "localhost:50051";
    auto connStatus = proxy.connectToService(serverAddress, true);
    if (!connStatus.ok())
        return EXIT_FAILURE;
    }
    std::cout << "Proxy has connected to service" << std::endl;


Below, you find documentation on all the methods of the proxy. For an introduction and more general documentation of 
how the *Visualization Streamer Service* works, please see :doc:`service`.

.. note::
    In the subsequent chapter, any reference to the *Service* means the *Visualization Streamer Service*.

*******************
Expected and Status
*******************

``Expected`` is a templated class that can either hold a given DataType or an error if something goes wrong. If 
``Expected::ok()`` returns true, it holds a value of the given DataType. If false, it holds an error message.

**Example usage**

.. code-block:: cpp

    const vsp::ExpectedKey eMeshKey = 
       m_proxy->pushIndexedPolygonMesh(vertexArr, vertsPerPolyArr, indexArr);
    if (!eMeshKey.ok())
    {
        return eMeshKey.errorMessage();
    }

    vsp::MeshInstance instance;
    instance.meshKey = eMeshKey.value();

``Status`` is similar to ``Expected`` but just with a boolean type. So it has the ``ok()`` method and the 
``errorMessage()`` method, but not the ``value()`` method, as this is sort of returned by ``ok()``.

ResourceKey
===========

A ``ResourceKey`` is an object identifier referencing a data/instance object stored in the *Service*. All the 
``pushXX()`` methods and the ``addXXGroup()`` methods return a ``ResourceKey`` and this key is used to reference the 
data in the Instances or the Frames. 

.. code-block:: cpp

    using ResourceKey = std::string;
    using ExpectedKey = Expected<ResourceKey>;

So ``ExpectedKey`` is either a ``ResourceKey`` or an error object.

Tags
====

Meshes, Point Clouds, Particle Traces and Textures have an optional user-defined tag (std::string) that can be 
specified when the data is pushed. This tag is not used by the *Service* but can be retrieved in the client side 
*Stream Model*. 


**************
Documentation
**************

pushIndexedPolygonMesh
======================

.. code-block:: cpp

    virtual ExpectedKey pushIndexedPolygonMesh(
        const std::vector<float>& vertexArr,
        const std::vector<vsp::ubyte>& verticesPerPolyArr,
        const std::vector<vsp::uint>& indexArr,
        std::string tag = "",
        const OptionalMeshData& optionalMeshData = OptionalMeshData()
    ) = 0;

Sends a polygon mesh with a varying number of vertices per polygon to the *Service*. The polygons can have two or 
more vertices but must be convex for proper rendering. The polygon will rendered according to the specified 
*MeshSettings*. 

- **Parameters:**    

  - `vertexArr`: A list of float coordinates (x, y, z).  
  - `verticesPerPolyArr`: Number of vertices for each polygon.  
  - `indexArr`: Defining the polygons. Indices into the vertexArr.  
  - `tag`: A user-defined optional tag. Not used by the *Service* but can be retrieved in the client side *Stream Model*  
  - `optionalMeshData`: Optional per-polygon and per-vertex user-defined ids. Not used by the *Service* but can be 
    retrieved in the client side *Stream Model*.  

pushIndexedSingleTypePolygonMesh
================================

.. code-block:: cpp

    virtual ExpectedKey pushIndexedSingleTypePolygonMesh(
        const std::vector<float>& vertexArr,
        vsp::ubyte fixedVerticesPerPoly,
        const std::vector<vsp::uint>& indexArr,
        std::string tag = "",
        const OptionalMeshData& optionalMeshData = OptionalMeshData()
    ) = 0;

Sends a polygon mesh with a fixed number of vertices per polygon to the *Service*. The polygons can have two or more 
vertices but must be convex for proper rendering. The polygon will rendered according to the specified *MeshSettings*.  


- **Parameters:**    

  - `vertexArr`: A list of float coordinates (x, y, z).  
  - `fixedVerticesPerPoly`: The number of vertices per polygon in the mesh.  
  - `indexArr`: Defining the polygons. Indices into the  vertexArr. 
  - `tag`: A user-defined optional tag. Not used by the *Service* but can be retrieved in the client side *Stream Model*  
  - `optionalMeshData`: Optional per-polygon and per-vertex user-defined ids. Not used by the *Service* but can be 
    retrieved in the client side *Stream Model*  

pushMeshScalar
==============

.. code-block:: cpp

    virtual ExpectedKey pushMeshScalar(
        ResourceKey bindToMeshKey,
        ResultMapping resultMapping,
        const std::vector<float>& valueArr
    ) = 0;

Sends an array of scalar results (1D field) that can be mapped to a *Mesh* to the *Service*.    

- **Parameters:**    

  - `bindToMeshKey`: The ResourceKey of the the *Mesh* object (returned by ``pushIndexedPolygonMesh()`` or 
    ``pushIndexedSingleTypePolygonMesh()``)
  - `resultMapping`: The result mapping for the *valueArr*. Can be per vertex, per polygon, per polygon-vertex. 
  - `valueArr`: One scalar result value per vertex, polygon or polygon-vertex in the *Mesh*.

pushMeshVector
==============

.. code-block:: cpp

    virtual ExpectedKey pushMeshVector(
        ResourceKey bindToMeshKey,
        ResultMapping resultMapping,
        const std::vector<float>& vectorArr
    ) = 0;

Sends an array of vector results (3D field) that can be mapped to a *Mesh* to the *Service*.    

- **Parameters:**    

  - `bindToMeshKey`: The ResourceKey of the the *Mesh* object (returned by ``pushIndexedPolygonMesh()`` or 
    ``pushIndexedSingleTypePolygonMesh()``)
  - `resultMapping`: The result mapping for the *vectorArr*. Can be per vertex, per polygon, per polygon-vertex. 
  - `vectorArr`: One vector result (x,y,z) value per vertex, polygon or polygon-vertex in the *Mesh*.

pushMeshDisplacement
====================

.. code-block:: cpp

    virtual ExpectedKey pushMeshDisplacement(
        ResourceKey bindToMeshKey,
        const std::vector<float>& displacementArr
    ) = 0;

Sends an array of displacement results (x,y,z) that can be mapped to a *Mesh* to the *Service*.    

- **Parameters:**    

  - `bindToMeshKey`: The ResourceKey of the the *Mesh* object (returned by ``pushIndexedPolygonMesh()`` or 
    ``pushIndexedSingleTypePolygonMesh()``)
  - `displacementArr`: One displacement vector (x,y,z) per vertex in the mesh in the *Mesh*. The nodes in the mesh will 
    be displaced with the given values.

pushPointCloud
==============

.. code-block:: cpp

    virtual ExpectedKey pushPointCloud(
        const std::vector<float>& vertexArr,
        std::string tag = ""
    ) = 0;

Sends an array of points to the *Service*. The point cloud can be visualized as points but can also have vector results 
at each point to allow for visualization of vector arrows not tied to a mesh.

- **Parameters:**     

  - `vertexArr`: Array with 3D coordinates (x,y,z) for the points.   
  - `tag`: A user-defined optional tag. Not used by the *Service* but can be retrieved in the client side *Stream Model*. 

pushPointCloudVector
====================

.. code-block:: cpp

    virtual ExpectedKey pushPointCloudVector(
        ResourceKey bindToPointCloudKey,
        const std::vector<float>& vectorArr
    ) = 0;

Sends an array of vector results (3D field) that can be mapped on a *Point Cloud* to the *Service*.    

- **Parameters:**     

  - `bindToPointCloudKey`: The ResourceKey of the the *Point Cloud* object (returned by ``pushPointCloud()``)  
  - `vectorArr`: One vector result (x,y,z) value per point in the *Point Cloud*

pushPointCloudScalar
====================

.. code-block:: cpp

    virtual ExpectedKey pushPointCloudScalar(
        ResourceKey bindToPointCloudKey,
        const std::vector<float>& valueArr
    ) = 0;

Sends an array of scalar results (1D field) that can be mapped on a *Point Cloud* to the *Service*.    

- **Parameters:**     

  - `bindToPointCloudKey`: The ResourceKey of the the *Point Cloud* object (returned by ``pushPointCloud()``)
  - `valueArr`: One scalar result value per point in the *Point Cloud*

pushPointCloudColors
====================

.. code-block:: cpp

    virtual ExpectedKey pushPointCloudColors(
        ResourceKey bindToPointCloudKey,
        const std::vector<ubyte>& rgbByteColorArr
    ) = 0;

Sends an array of rgb byte colors per point in a *Point Cloud* to the *Service*.    

- **Parameters:**     

  - `bindToPointCloudKey`: The ResourceKey of the the *Point Cloud* object (returned by ``pushPointCloud()``)
  - `rgbByteColorArr`: Array of byte colors (r,g,b) per point in the *Point Cloud*

pushParticleTrace
=================

.. code-block:: cpp

    virtual ExpectedKey pushParticleTrace(
        const std::vector<float>& positionArr,
        const std::vector<float>& timeStampArr,
        std::string tag = "",
        const OptionalParticleTraceData& optionalParticleTraceData = OptionalParticleTraceData()
    ) = 0;

Sends particle trace data to the *Service*.

- **Parameters:**     

  - `positionArr`: 3D coordinates of the points on the particle trace (x,y,z)
  - `timeStampArr`: Array of time stamps for each 3D coordinate (used to animate)
  - `tag`: A user-defined optional tag. Not used by the *Service* but can be retrieved in the client side *Stream Model*  
  - `optionalParticleTraceData`: Optional scalar result per point in the particle trace (can be used for color mapping).

pushTexture
===========

.. code-block:: cpp

    virtual ExpectedKey pushTexture(
        ushort imageWidth,
        ushort imageHeight,
        const std::vector<ubyte>& pixelRgbaArr,
        const TextureOptions& textureOptions,
        std::string tag = ""
    ) = 0;

Sends a 2D texture image to the *Service*. The texture can be mapped on a Mesh surface.

- **Parameters:**     

  - `imageWidth`: The width of the texture
  - `imageHeight`: The height of the texture
  - `pixelRgbaArr`: 3D coordinates of the points on the particle trace (x,y,z)
  - `textureOptions`: Options for the texture mapping: min and mag filter, wrap mode and environment mapping.
  - `tag`: A user-defined optional tag. Not used by the *Service* but can be retrieved in the client side *Stream Model*  


pushMeshTextureCoords
=====================

.. code-block:: cpp

    virtual ExpectedKey pushMeshTextureCoords(
        ResourceKey bindToMeshKey,
        ResultMapping resultMapping,
        const std::vector<float>& textureCoord2dArr
    ) = 0;

Sends an array if 2D texture coordinates (s, t) to the *Service*. The array mush have one texture coordinate per vertex 
in the associated mesh.

- **Parameters:**     

  - `bindToMeshKey`: The ResourceKey of the the *Mesh* object (returned by ``pushIndexedPolygonMesh()`` or 
    ``pushIndexedSingleTypePolygonMesh()``)
  - `resultMapping`: The result mapping for the (s,t) coordinates in *textureCoord2dArr*. Can be per vertex, per polygon, 
    per polygon-vertex. 
  - `textureCoord2dArr`: Array of 2D texture coordinates (s,t) per vertex, polygon or polygon vertex in the *Mesh*.


pushTransformArray
==================

.. code-block:: cpp

    virtual ExpectedKey pushTransformArray(
        const std::vector<float>& matrixArr
    ) = 0;

Sends an array of 4x4 Transformation Matrices to the *Service*. The matrices can be referenced in *Mesh Instances* and 
be used to do rigid body transformations (either for animations or for instancing). Matrices are specified as 16 floats 
in row, column order:

:: 
 
   | m00  m01  m02  m03 |     | 0  4   8  12 | 
   | m10  m11  m12  m13 |     | 1  5   9  13 | 
   | m20  m21  m22  m23 |     | 2  6  10  14 | 
   | m30  m31  m32  m33 |     | 3  7  11  15 | 


This is consistent with the way matrices are represented in OpenGL. To exemplify, translation values are stored in 
elements 12,13,14; see figure below:

::

   | 1  0  0 Tx |
   | 0  1  0 Ty |
   | 0  0  1 Tz |
   | 0  0  0  1 |


pushMeshSettings
================

.. code-block:: cpp

    virtual ExpectedKey pushMeshSettings(
        const MeshSettings& settings
    ) = 0;


Sends settings to describe how to render the *Mesh* to the *Service*. The mesh settings consist of draw style (surface, 
surface mesh, surface outline mesh, lines, points, outline, hidden lines removed), color, opacity (1.0 opaque, 0.0 fully 
transparent (invisible)) and smooth (per-vertex)/flat (per polygon) shading. 

The settings will be mapped to a *Mesh* in the *Mesh Instance* object.

pushPointCloudSettings
======================

.. code-block:: cpp

    virtual ExpectedKey pushPointCloudSettings(
        const PointCloudSettings& settings
    ) = 0;

Sends settings to describe how to render the *Point Cloud* to the *Service*. The settings consists of a single color 
for all points.

The settings will be mapped to a *Point Cloud* in the *Point Cloud Instance* object.

pushScalarSettings
==================
.. code-block:: cpp

    virtual ExpectedKey pushScalarSettings(
        const ScalarSettings& settings
    ) = 0;

Sends *Scalar* settings to the *Service*. The scalar settings describe how to visualize the mapped *Scalar* result on 
a *Mesh*. The settings include the minimum and maximum range for the color mapping. More settings will be added.

pushVectorSettings
==================

.. code-block:: cpp

    virtual ExpectedKey pushVectorSettings(
        const VectorSettings& settings
    ) = 0;

Sends *Vector* settings to the *Service*. The vector settings describe how to visualize the vector result. The settings 
include a single color and a scalar factor. More settings will be added.

pushParticleTraceSettings
=========================

.. code-block:: cpp

    virtual ExpectedKey pushParticleTraceSettings(
        const ParticleTraceSettings& settings
    ) = 0;

Sends *Particle Trace* settings to the *Service*. The particle trace settings describe how to render the particle 
traces. This includes settings for visualization style (comets, spheres, cylinders), color, radius, settings for 
animation.

addMeshGroup
============

.. code-block:: cpp

    virtual ExpectedKey addMeshGroup(
        const std::vector<MeshInstance>& instanceArr
    ) = 0;

Sends a mesh instance description to the *Service*. The *MeshInstance* specifies an instance/configuration of a mesh: 
ResourceKeys for *Mesh* and *MeshSettings*, which *Scalar* to map on the surface (and its settings), which *Vector* 
result to map on the surface (and its settings) (can be more than one), texture and settings, transform array 
ResourceKey and the index of the matrix to use for this mesh. 

.. code-block:: cpp

    struct MeshInstance
    {
        ResourceKey                     meshKey;
        ResourceKey                     meshSettingsKey;

        std::optional<ResourceKey>      mapScalarKey;
        std::optional<ResourceKey>      mapScalarSettingsKey;
        std::optional<ResourceKey>      textureKey;
        std::optional<ResourceKey>      textureCoordsKey;
        std::vector<MeshVectorInstance> vectorInstanceArr;

        std::optional<ResourceKey>      transformArrayKey;
        int                             transformArrayIndex = 0;

        std::optional<ResourceKey>      parentMeshGroupKey;
        std::optional<std::string>      tag;
    };

A *meshKey* and *meshSettingsKey* must always be specified. 

For color mapping of the mesh, one of the following combinations must be specified

- *mapScalarKey* + *mapScalarSettingsKey* can be used to map a scalar field to the mesh.
- *textureKey* + *textureCoordsKey* can be used to add a texture to the mesh. Texture coords are 2D coords per vertex.

Any number of vector fields can be mapped onto the mesh as specified in the *vectorInstanceArr*, each defined by a 
MeshVectorSpec.

You can also specify a ``parentMeshGroupKey``, which indicates that this group is dependent on another mesh group (will 
not be visualized on the client until both are ready). This is useful if you have e.g. a custom element mesh provided 
as lines in this group, but would not like it to show up before the associated *Mesh* with the surface polygons.

addPointCloudGroup
==================

.. code-block:: cpp

    virtual ExpectedKey addPointCloudGroup(
        const std::vector<PointCloudInstance>& instanceArr
    ) = 0;

Sends a point cloud instance description to the *Service*. The *PointCloudInstance* specifies an instance/configuration 
of a point cloud: ResourceKeys for *PointCloud* and *PointCloudSettings*, *Vector* and *VectorSettings*,  *Scalar* and 
*ScalarSettings* and *Colors* for per-point/vector coloring.

.. code-block:: cpp

    struct PointCloudInstance
    {
        ResourceKey                     pointCloudKey;
        ResourceKey                     pointCloudSettingsKey;

        std::optional<ResourceKey>      mapScalarKey;
        std::optional<ResourceKey>      mapScalarSettingsKey;
        std::optional<ResourceKey>      colorsKey;
        std::optional<ResourceKey>      vectorKey;
        std::optional<ResourceKey>      vectorSettingsKey;

        std::optional<ResourceKey>      parentMeshGroupKey;
        std::optional<std::string>      tag;
    };

A *pointCloudKey* and *pointCloudSettingsKey* must always be specified. 

For color mapping of the points/vectors, one of the following combinations must be specified

- *mapScalarKey* + *mapScalarSettingsKey* can be used to map a scalar field to the mesh.
- *colorsKey* can be used to specify one RGB color per point/vector.

If the point cloud should show vectors, you need to specify both a *vectorKey* and a *vectorSettingsKey*.

You can also specify a ``parentMeshGroupKey``, which indicates that this *PointCloud* is dependent on a mesh group (will 
not be visualized on the client until both are ready). This is useful if you have e.g. regular sampled vectors on a 
cutting plane, but would not like the vectors to show up before the associated *Mesh* with the surface polygons.


addParticleTraceGroup
=====================

.. code-block:: cpp

    virtual ExpectedKey addParticleTraceGroup(
        const std::vector<ResourceKey>& particleTraceKeyArr,
        ResourceKey particleTraceSettingsKey
    ) = 0;

Sends a particle trace group instance to the *Service*. This allows you to specify an array of ResourceKeys for 
*ParticleTrace* and a single ResourceKey for the *ParticleTraceSettings*. These settings will be shared by all 
ParticleTraces in this instance. 

createStream
============

.. code-block:: cpp

    virtual Status createStream(
        std::string streamName,
        std::string description
    ) = 0;

Create a stream with the given `streamName` and a description. You need at least one stream to use the *Service*. 

See description of *Stream* in :doc:`service`. 

deleteStream
============

.. code-block:: cpp

    virtual Status deleteStream(
        std::string streamName
    ) = 0;

Delete the stream with the given *streamName*. This will delete all *Frame*\s associated with the stream and can allow 
for memory cleanup of unreferenced objects using the ``deleteUnreferencedData()`` method.

createAndPublishSingleFrame
===========================

.. code-block:: cpp

    virtual ExpectedKey createAndPublishSingleFrame(
        std::string streamName,
        const Frame& frame
    ) = 0;


Convenience function for creating and publishing a single frame in one call, returns the resource key of the frame.

Similar to ``createFrame()``, this function is a server-side **barrier** that does not return until the frame is ready 
to stream from the server.

The function does the following:

  - Deletes all existing frames (`deleteAllFrames(streamName)`)
  - Creates a new frame (`createFrame(streamName, frame)`)
  - Shows/publishes the single frame (`publishFrames(streamName, [frame])`)

createFrame
===========

.. code-block:: cpp

    virtual ExpectedKey createFrame(
        std::string streamName,
        const Frame& frame
    ) = 0;

Create a Frame in the given *Stream* with the name *streamName*. The *Frame* struct has an array of *ResourceKeys* for 
*MeshInstances*, *PointCloudInstances* and *ParticleTraceInstances*. 

.. code-block:: cpp

    struct Frame
    {
        std::vector<ResourceKey>    meshGroupKeyArr;
        std::vector<ResourceKey>    pointCloudGroupKeyArr;
        std::vector<ResourceKey>    particleTraceGroupKeyArr;
    };

`createFrame()` is a server-side **barrier** that does not return until the *Frame* is ready to stream from the server.

publishFrames
=============

.. code-block:: cpp

    virtual Status publishFrames(
        std::string streamName,
        const std::vector<ResourceKey>& frameKeyArr
    ) = 0;

Publish the *Frames* with the ResourceKeys specified in the `frameKeyArr` on the *Stream* with the name `streamName`. 
Unless you have transient animations, you will only include one Frame (one ResourceKey) in the `frameKeyArr`. 

PublishFrame(s) tells all the client side *Stream Model* connected to the given `streamName` to show the given 
*Frame*\(s). 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.

deleteFrames
============

.. code-block:: cpp

    virtual Status deleteFrames(
        std::string streamName,
        const std::vector<ResourceKey>& frameKeyArr
    ) = 0;

Delete the specified Frames with the ResourceKeys in `frameKeyArr`. This will remove the Frame specifications from the 
*Service* and make it possible to clean up any unreferenced data (by using the ``deleteUnreferencedData()`` method).

deleteAllFrames
===============

.. code-block:: cpp

    virtual Status deleteAllFrames(
        std::string streamName
    ) = 0;

Removes all frames from a specific stream.  This will make it possible to clean up any unreferenced data (by using the 
``deleteUnreferencedData()`` method).

deleteUnreferencedData
======================

.. code-block:: cpp

    virtual Status deleteUnreferencedData() = 0;

This method will delete any data objects that are not referenced (directly or indirectly) by the current list of 
*Frames* in any of the current *Streams*. 

We will add more fine-grained control for garbage collection and memory management in later versions of the product.


***************
Not Implemented
***************

The following methods are not implemented in the *VizStreamerProxy* class:

pushPointCloudScalar
====================

.. code-block:: cpp

    virtual ExpectedKey pushPointCloudScalar(
        ResourceKey bindToPointCloudKey,
        const std::vector<float>& valueArr
    ) = 0;

pushPointCloudColors
====================

.. code-block:: cpp

    virtual ExpectedKey pushPointCloudColors(
        ResourceKey bindToPointCloudKey,
        const std::vector<ubyte>& rgbByteColorArr
    ) = 0;

pushParticleTrace
=================

.. code-block:: cpp

    virtual ExpectedKey pushParticleTrace(
        const std::vector<float>& positionArr,
        const std::vector<float>& timeStampArr,
        std::string tag = "",
        const OptionalParticleTraceData& optionalParticleTraceData = OptionalParticleTraceData()
    ) = 0;

pushParticleTraceSettings
=========================

.. code-block:: cpp

    virtual ExpectedKey pushParticleTraceSettings(
        const ParticleTraceSettings& settings
    ) = 0;

addParticleTraceGroup
=====================

.. code-block:: cpp

    virtual ExpectedKey addParticleTraceGroup(
        const std::vector<ResourceKey>& particleTraceKeyArr,
        ResourceKey particleTraceSettingsKey
    ) = 0;

deleteStream
============

.. code-block:: cpp

    virtual Status deleteStream(
        std::string streamName
    ) = 0;

deleteFrames
============

.. code-block:: cpp

    virtual Status deleteFrames(
        std::string streamName,
        const std::vector<ResourceKey>& frameKeyArr
    ) = 0;

Other Items Still Todo
======================

  - Streaming of initial low-res geometry
  - The parentMeshKey concept is still not implemented
