.. _animation-page:

#########
Animation 
#########

There are four main different types of animations supported in |ProductName|.

-   **State animation (also known as transient animation)** |br|
    Data is stored in a number of states (time steps, frequencies, load cases) and we
    would like to create an animation running through all the specified states.
-   **Modeshape animation.** |br|
    In this case we have a single state with a displacement result. The animation will then animate between the 
    non-displaced and the displaced result, create a modeshape animation.
-   **Particle trace animation** |br|
    In this case we would like to animate the particle traces to visualize the flow defined by a vector field.
-   **Cutting plane animation** |br|
    Animates the movement of a cutting plane through the model.

To ensure the best possible performance, all animations in |ProductName| require the user to first setup the 
animation. Here all relevant data is loaded into the data source and the visual representation (display model) of the 
data is generated. This will ensure that once the animation is setup, it can run at the highest possible frame rate.

Below we describe how to setup these four forms of animations, and how to run and control the animation after it has 
been prepared.

.. note::
    When setting up and running animations, it is very important that you have found an efficient way of representing
    your data in the data source. Please consult :ref:`data-page` for guidance on this topic.

************************
Setting up the Animation
************************

If you are using a :class:`memory data source <cee::ug::DataSourceMemory>` you will need to make sure that the 
:class:`DataSource <cee::ug::DataSource>` has all the needed data before you setup the animation. If you are using an 
:class:`interface based data source <cee::ug::DataSourceInterface>`, a :class:`custom data reader <cee::ug::DataReader>` 
or a VTFx/ImportCae data source you can skip this step as |ProductName| will automatically load the data needed.

Then you need to configure the :class:`ModelSpec <cee::ug::ModelSpec>` with the results you would like to visualize.

State Animation
===============

For state animations, use the :func:`ModelSpec::setStateIds <cee::ug::ModelSpec::setStateIds>` to specify all states in 
the order they should appear in the animation.

Then call :func:`updateVisualization() <cee::ug::UnstructGridModel::updateVisualization>` to setup the animation.

.. code-block:: cpp

    std::vector<gc::ug::StateInfo> stateInfos = source->directory()->stateInfos();
    std::vector<int> stateIds;
    for (size_t i = 0; i < stateInfos.size(); i++)
    {
        int stateId = stateInfos[i].id();
        stateIds.push_back(stateId);
    }

    unstructModel->modelSpec().setStateIds(stateIds);

Modeshape Animation
===================

For modeshape animations, use the :func:`ModelSpec::modeShapeAnimation() <cee::ug::ModelSpec::modeShapeAnimation>` 
method to specify the settings for the mode shape animation you would like to generate.

Then call :func:`updateVisualization() <cee::ug::UnstructGridModel::updateVisualization>` to setup the animation.

.. code-block:: cpp

    unstructModel->modelSpec().modeShapeAnimation().setFrameCount(30);


Particle Trace Animation
=========================

Setup the particle trace as you want it (see :ref:`particle-trace-page` for more info). There is no specific setup 
needed (e.g. number of frames) for particle traces. See the section below on how to run the animation.

Cutting Plane Animation
========================

Set up the cutting plane animation using a :class:`cee::ug::CuttingPlaneAnimation` object. Specify number of frames and 
the distance should move per frame.

.. code-block:: cpp

    cee::ug::CuttingPlaneAnimation cpAnim(myUgModel, 0);
    cpAnim.setPerFrameDistance(0.5);
    cpAnim.generateAnimation();

*********************
Running the Animation
*********************

To run animations, you will need to use a timer. Timers are UI Toolkit and platform dependent, so please consult your UI 
Toolkit for tips on how to use timers. You need to create a timer that fires at least at the frequency you want your 
animation to run at.
When the timer is called, you update the animation to set the next frame/particle trace time as shown below.

Please consult the DemoApp in the Examples folder **(Examples/Qt/QtDemoApp/AnimationWidget.cpp)** for a more complete 
example on how to handle both state and particle trace animations in your application.

.. note::

    Do not call :func:`updateVisualization() <cee::ug::UnstructGridModel::updateVisualization>` before changing frames. 
    :func:`updateVisualization() <cee::ug::UnstructGridModel::updateVisualization>` should only be called when setting 
    up the animation, never when running it.

State Animation and Modeshape Animation
========================================

For state and modeshape animations you use the 
:func:`UnstructGridModel::setCurrentFrameIndex() <cee::ug::UnstructGridModel::setCurrentFrameIndex>` method to specify 
which of the generated frames to show in the associated view.

So when the timer triggers, do the following for animations running forward.

.. code-block:: cpp

    size_t newIndex = m_unstructModel->currentFrameIndex();

    if (newIndex < m_unstructModel->frameCount() - 1)
    {
        newIndex++;
    }
    else
    {
        newIndex = 0;
    }

    m_unstructModel->setCurrentFrameIndex(newIndex);
    m_view->requestRedraw();


As you are in control of setting the current animation frame, it is easy to do animation that runs backwards, 
bouncing (0..N-1..0..N-1) and any order you would like. You also decide when the animation frame changes if you want to 
synchronize the animation with other items or scaled real time.

Particle Trace Animations
=========================

To animate particle traces, you set the current particle trace time in the 
:class:`UnstructGridModel <cee::ug::UnstructGridModel>` by using the 
:func:`setParticleTraceTime() <cee::ug::UnstructGridModel::setParticleTraceTime>` method.

.. code-block:: cpp

    double minimumTraceTime = m_unstructModel->particleTraceGroup(0)->minimumTraceTime(0);
    double maximumTraceTime = m_unstructModel->particleTraceGroup(0)->maximumTraceTime(0);

    double particleTraceDelta = (maximumTraceTime - minimumTraceTime) / numberOfSteps;

    double newTime = m_unstructModel->particleTraceTime() + particleTraceDelta;

    if (newTime > m_unstructModel->particleTraceGroup(0)->maximumTraceTime(0))
    {
        newTime = m_unstructModel->particleTraceGroup(0)->minimumTraceTime(0);
    }

    m_unstructModel->setParticleTraceTime(newTime);
    m_view->requestRedraw();

