IEnumerator meshAnimationOptimized()
    {
        //It is important to create a copy of the vertices and only use "inputMesh.vertices" only once
        // since this is a get function. Meaning in every call of the function the mesh will be copied.
        Vector3[] inputVertices    = InputMesh.vertices;
        int       numberOfVertices = inputVertices.Length;

        //We look at our input being 2 dimensional. One dimension is the number of vertices,
        //the other dimension is the vector x,y,z

        //We create lines for the first dimension the number of vertices
        int numberOfVertexCubits = Mathf.CeilToInt(Mathf.Log(numberOfVertices) / Mathf.Log(2));

        //The lines are needed to encode the data in a way that encoding of neighbouring vertices only differ in 1 bit
        int[] linesVertices = QuantumImageHelper.MakeLinesInt(numberOfVertexCubits);

        //We create lines for the second dimension the vector x,y,z so there are only 3 values (thats where the 3 comes from).
        //The 2 is to transform the thing to base 2 since we need the logarithm in base 2.
        int numberOfVectorQubits = Mathf.CeilToInt(Mathf.Log(3) / Mathf.Log(2));

        //The lines are needed to encode the data in a way that the encoding of x and y as well as y and z only differ in 1 bit.
        int[] linesVector = QuantumImageHelper.MakeLinesInt(numberOfVectorQubits);

        //Creating a circuit big enough to fit in the mesh data
        int            numberOfQubits = numberOfVertexCubits + numberOfVectorQubits;
        QuantumCircuit circuit        = new QuantumCircuit(numberOfQubits, numberOfQubits, true);

        //Since we work with probabilities, we need the values to be positive (or 0).
        //Therefore we want to translate the values adding an offset to our values, such that they become positive.

        //Getting the smallest (most negative) values to use for the displacement
        //initiate values as 0
        float minX = 0;
        float minY = 0;
        float minZ = 0;

        for (int i = 0; i < inputVertices.Length; i++)
        {
            if (inputVertices[i].x < minX)
            {
                minX = inputVertices[i].x;
            }
            if (inputVertices[i].y < minY)
            {
                minY = inputVertices[i].y;
            }
            if (inputVertices[i].z < minZ)
            {
                minZ = inputVertices[i].z;
            }
        }

        //Needed to transform the position of our 2 dimensions mentioned above into a single array.
        //The indexes look like this:  0_X, 0_Y, 0_Z, 0_?, 1_X, 1_Y, 1_Z.... Where 0,1 etc stand for the vertex number
        //X,Y,Z stands for the respective coordinates and ? is just a placeholder which is not really needed (but we need to have a power of 2 so 4 values for our 3)
        int maxHeight = linesVector.Length;

        for (int i = 0; i < numberOfVertices; i++)
        {
            //We use the lines produced above to calculate the new position
            int index = linesVertices[i] * maxHeight;
            //We interpret the values as probabilities. And the amplitudes are the square root of the probabilities.
            circuit.Amplitudes[index + linesVector[0]].Real = Math.Sqrt(inputVertices[i].x - minX);
            circuit.Amplitudes[index + linesVector[1]].Real = Math.Sqrt(inputVertices[i].y - minY);
            circuit.Amplitudes[index + linesVector[2]].Real = Math.Sqrt(inputVertices[i].z - minZ);
        }

        //We need to normalize the circuit, since probabilities should add up to 1.
        //We store the factor used for normalization in order to reverse this scaling later.
        circuit.Normalize();
        double normalizationFactor = circuit.OriginalSum;

        //We don't want to allocate as phew memory as possible in order to minimize garbage collection
        //Therefore, we reuse the defined arrays
        double[]  realAmplitudes = new double[circuit.AmplitudeLength];
        Vector3[] outPutVertices = new Vector3[numberOfVertices];

        //Making a copy of the amplitudes of the circuit
        for (int i = 0; i < circuit.AmplitudeLength; i++)
        {
            realAmplitudes[i] = circuit.Amplitudes[i].Real;
        }

        //Creating a new mesh, at this point it is just a copy of the input mesh
        Mesh outputMesh = new Mesh();

        outputMesh.name      = InputMesh.name + " blurred";
        outputMesh.vertices  = inputVertices;
        outputMesh.triangles = InputMesh.triangles;
        outputMesh.uv        = InputMesh.uv;
        outputMesh.RecalculateNormals();
        outputMesh.RecalculateTangents();
        MicroQiskitSimulator simulator = new MicroQiskitSimulator();

        double[]        probs      = new double[circuit.AmplitudeLength]; //simulator.GetProbabilities(circuit);
        ComplexNumber[] amplitudes = new ComplexNumber[circuit.AmplitudeLength];

        //Setting the new mesh to the target
        //We can now just manipulate the vertices of this mesh in order to change it.
        //No need to create new meshes
        TargetMesh.sharedMesh = outputMesh;
        OutputMesh            = outputMesh;

        float rotation = 0.0f;
        float progress = 0;

        //Making sure to have no endless loop
        if (Duration <= 0)
        {
            Duration = 1;
        }

        //Creating an animation by blurring the mesh step by step
        //Duration is the duration of the animation, StartRotation and Endrotation give
        //The starting points and endpoints of the animation the rest is interpolated.
        while (progress < 1)
        {
            //Calculating progress for the animation
            progress += Time.deltaTime / Duration;
            //Rotation is interpolated between endRotation and startRtoation depending on progress
            rotation = progress * EndRotation + (1 - progress) * StartRotation;

            //Resetting the circuit (deleting the gates)
            circuit.ResetGates();
            //Reusing the circuit by filling in the original values before the calculation again
            for (int i = 0; i < circuit.AmplitudeLength; i++)
            {
                circuit.Amplitudes[i].Real = realAmplitudes[i];
            }

            //Applying the operation to the circuit (the blur effect)
            ApplyPartialQ(circuit, rotation);

            //Calculating probabilities
            simulator.CalculateProbabilities(circuit, ref probs, ref amplitudes);

            //Filling in the new calculated values into the vertices
            for (int i = 0; i < numberOfVertices; i++)
            {
                int index = linesVertices[i] * maxHeight;
                //Since we have probabilities already we do not need to square them.
                //We undo the normalization from above and the translation (offset) from the beginning
                outPutVertices[i].x = (float)(probs[index + linesVector[0]] * normalizationFactor) + minX;
                outPutVertices[i].y = (float)(probs[index + linesVector[1]] * normalizationFactor) + minY;
                outPutVertices[i].z = (float)(probs[index + linesVector[2]] * normalizationFactor) + minZ;
            }

            //We set the new vertices to the mesh, this way the mesh changes its form automatically
            //and we do not need to construct a new mesh.
            outputMesh.vertices = outPutVertices;
            //wait until next frame.
            yield return(null);
        }

        // Reverse animation going back to startRotation
        if (reverseAnimation)
        {
            while (progress > 0)
            {
                //Calculating progress for the animation going back
                progress -= Time.deltaTime / Duration;
                //Rotation is interpolated between endRotation and startRtoation depending on progress
                rotation = progress * EndRotation + (1 - progress) * StartRotation;

                //Resetting the circuit (deleting the gates)
                circuit.ResetGates();
                //Reusing the circuit by filling in the original values before the calculation again
                for (int i = 0; i < circuit.AmplitudeLength; i++)
                {
                    circuit.Amplitudes[i].Real = realAmplitudes[i];
                }

                //Applying the operation to the circuit (the blur effect)
                ApplyPartialQ(circuit, rotation);

                //Calculating probabilities
                simulator.CalculateProbabilities(circuit, ref probs, ref amplitudes);

                //Filling the new calculated values into the vertices
                for (int i = 0; i < numberOfVertices; i++)
                {
                    int index = linesVertices[i] * maxHeight;
                    //Since we have probabilities already we do not need to square them.
                    //We undo the normalization from above and the translation (offset) from the beginning
                    outPutVertices[i].x = (float)(probs[index + linesVector[0]] * normalizationFactor) + minX;
                    outPutVertices[i].y = (float)(probs[index + linesVector[1]] * normalizationFactor) + minY;
                    outPutVertices[i].z = (float)(probs[index + linesVector[2]] * normalizationFactor) + minZ;
                }

                outputMesh.vertices = outPutVertices;

                //We set the new vertices to the mesh, this way the mesh changes its form automatically
                //and we do not need to construct a new mesh.outputMesh.vertices = outPutVertices;
                //wait until next frame.
                yield return(null);
            }
        }
    }
    /// <summary>
    /// Creates a blurred version of the input mesh, according to the rotation. The bigger the rotation the stronger the blur effect.
    /// The model gets unrecognizeable as soon as the rotation gets to big
    /// </summary>
    /// <param name="inputMesh">The mesh to produce a blurred version of.</param>
    /// <param name="rotation">Can be between 0 and 3.1415 (pi). For starting 0.1 would be a good value.</param>
    /// <returns>A blurred (distorted) mesh of the original input mesh. </returns>
    public Mesh CreateBluredMesh(Mesh inputMesh, float rotation)
    {
        //It is important to create a copy of the vertices and only use "inputMesh.vertices" only once
        // since this is a get function. Meaning in every call of the function the mesh will be copied.
        Vector3[] vertices         = inputMesh.vertices;
        int       numberOfVertices = vertices.Length;

        //We look at our input being 2 dimensional. One dimension is the number of vertices,
        //the other dimension is the vector x,y,z

        //We create lines for the first dimension the number of vertices
        int numberOfVertexCubits = Mathf.CeilToInt(Mathf.Log(numberOfVertices) / Mathf.Log(2));

        //The lines are needed to encode the data in a way that encoding of neighbouring vertices only differ in 1 bit
        int[] linesVertices = QuantumImageHelper.MakeLinesInt(numberOfVertexCubits);

        //We create lines for the second dimension the vector x,y,z so there are only 3 values (thats where the 3 comes from).
        //The 2 is to transform the thing to base 2 since we need the logarithm in base 2.
        int numberOfVectorQubits = Mathf.CeilToInt(Mathf.Log(3) / Mathf.Log(2));

        //The lines are needed to encode the data in a way that the encoding of x and y as well as y and z only differ in 1 bit.
        int[] linesVector = QuantumImageHelper.MakeLinesInt(numberOfVectorQubits);

        //Creating a circuit big enough to fit in the mesh data
        int            numberOfQubits = numberOfVertexCubits + numberOfVectorQubits;
        QuantumCircuit circuit        = new QuantumCircuit(numberOfQubits, numberOfQubits, true);

        //Since we work with probabilities, we need the values to be positive (or 0).
        //Therefore we want to translate the values adding an offset to our values, such that they become positive.

        //Getting the smallest (most negative) values to use for the displacement
        //initiate values as 0
        float minX = 0;
        float minY = 0;
        float minZ = 0;

        for (int i = 0; i < vertices.Length; i++)
        {
            if (vertices[i].x < minX)
            {
                minX = vertices[i].x;
            }
            if (vertices[i].y < minY)
            {
                minY = vertices[i].y;
            }
            if (vertices[i].z < minZ)
            {
                minZ = vertices[i].z;
            }
        }

        //Needed to transform the position of our 2 dimensions mentioned above into a single array.
        //The indexes look like this:  0_X, 0_Y, 0_Z, 0_?, 1_X, 1_Y, 1_Z.... Where 0,1 etc stand for the vertex number
        //X,Y,Z stands for the respective coordinates and ? is just a placeholder which is not really needed (but we need to have a power of 2 so 4 values for our 3)
        int maxHeight = linesVector.Length;

        for (int i = 0; i < numberOfVertices; i++)
        {
            //We use the lines produced above to calculate the new position
            int index = linesVertices[i] * maxHeight;
            //We interpret the values as probabilities. And the amplitudes are the square root of the probabilities.
            circuit.Amplitudes[index + linesVector[0]].Real = Math.Sqrt(vertices[i].x - minX);
            circuit.Amplitudes[index + linesVector[1]].Real = Math.Sqrt(vertices[i].y - minY);
            circuit.Amplitudes[index + linesVector[2]].Real = Math.Sqrt(vertices[i].z - minZ);
        }

        //We need to normalize the circuit, since probabilities should add up to 1.
        //We store the factor used for normalization in order to reverse this scaling later.
        circuit.Normalize();
        double normalizationFactor = circuit.OriginalSum;

        //We apply the effect to the circuit. Here this is the normal blur effect also used in the images.
        ApplyPartialQ(circuit, rotation);

        //Calculating the probabilities after having applied the operation above

        SimulatorBase simulator = new MicroQiskitSimulator();

        //MicroQiskitSimulator simulator = new MicroQiskitSimulator();
        //QiskitSimulator simulator = new QiskitSimulator();

        double[] probs = simulator.GetProbabilities(circuit);

        //Fill in the new calculated values back into the vertices
        for (int i = 0; i < numberOfVertices; i++)
        {
            int index = linesVertices[i] * maxHeight;

            //Since we have probabilities already we do not need to square them.
            //We undo the normalization from above and the translation (offset) from the beginning
            vertices[i].x = (float)(probs[index + linesVector[0]] * normalizationFactor) + minX;
            vertices[i].y = (float)(probs[index + linesVector[1]] * normalizationFactor) + minY;
            vertices[i].z = (float)(probs[index + linesVector[2]] * normalizationFactor) + minZ;
        }

        //creating the new mesh
        Mesh outputMesh = new Mesh();

        //setting the newly calculated vertices
        outputMesh.vertices = vertices;
        //Copying most stuff from original mesh
        outputMesh.name      = inputMesh.name + " blurred";
        outputMesh.triangles = inputMesh.triangles;
        outputMesh.uv        = inputMesh.uv;
        //Recalculating normals for correct lighning
        outputMesh.RecalculateNormals();

        //returning the mesh
        return(outputMesh);
    }