Esempio n. 1
0
    /// <summary>
    /// Sets the line width at the start and at the end.
    /// Note, varying line widths will have a segmented appearance vs. the smooth look one gets with the traditional linerenderer.
    /// </summary>
    public void SetWidth(float start, float end)
    {
        // Update internal data
        m_WidthStart = start;
        m_WidthEnd   = end;

        // See if the data needs initializing
        if (Initialize())
        {
            return;
        }

        // Otherwise, do fast setting
        var pointCounter   = 0;
        var elementCounter = 0;

        // We go through the element list, much like initialization, but only update the width part of the variables
        m_MeshData.SetElementSize(elementCounter, m_WidthStart);
        elementCounter++;
        pointCounter++;

        float stepSize    = 1.0f / Mathf.Max((m_Positions.Length - 1.0f), 1.0f);
        float stepPercent = stepSize;
        var   lastWidth   = m_WidthStart;

        while (pointCounter < m_Positions.Length)
        {
            var currentWidth = Mathf.Lerp(m_WidthStart, m_WidthEnd, stepPercent);

            m_MeshData.SetElementSize(elementCounter, lastWidth, currentWidth);
            elementCounter++;
            m_MeshData.SetElementSize(elementCounter, currentWidth);
            lastWidth = currentWidth;
            elementCounter++;
            pointCounter++;
            stepPercent += stepSize;
        }

        // Dirty all the MeshChain flags so everything gets refreshed
        m_MeshData.SetMeshDataDirty(VRLineRendererInternal.MeshChain.MeshRefreshFlag.Sizes);
        m_MeshNeedsRefreshing = true;
    }
    /// <summary>
    /// Updates the built-in mesh data for each control point of the trail
    /// </summary>
    void LateUpdate()
    {
        // We do  the actual internal mesh updating as late as possible so nothing ends up a frame behind
        var deltaTime = Time.deltaTime;

        // We give the editor a little help with handling delta time in edit mode
        if (Application.isPlaying == false)
        {
            deltaTime           = Time.realtimeSinceStartup - m_EditorDeltaHelper;
            m_EditorDeltaHelper = Time.realtimeSinceStartup;
        }

        // Get the current position of the renderer
        var currentPoint  = transform.position;
        var pointDistance = (currentPoint - m_LastRecordedPoint).sqrMagnitude;

        // Is it more than minVertexDistance from the last position?
        if (pointDistance > (m_MinVertexDistance * m_MinVertexDistance))
        {
            // In the situation we have no points, we need to record the start point as well
            if (m_PointIndexStart == m_PointIndexEnd)
            {
                m_Points[m_PointIndexStart]     = m_LastRecordedPoint;
                m_PointTimes[m_PointIndexStart] = m_Time;
            }

            // Make space for a new point
            var newEndIndex = (m_PointIndexEnd + 1) % m_MaxTrailPoints;

            // In the situation that we are rendering all available vertices
            // We can either keep using the current point, or take the last point, depending on the user's preference
            if (newEndIndex != m_PointIndexStart)
            {
                m_PointIndexEnd = newEndIndex;
                m_PointTimes[m_PointIndexEnd] = 0;
                m_UsedPoints++;
            }
            else
            {
                if (m_StealLastPointWhenEmpty)
                {
                    m_MeshData.SetElementSize(m_PointIndexStart * 2, 0);
                    m_MeshData.SetElementSize((m_PointIndexStart * 2) + 1, 0);
                    m_PointIndexStart             = (m_PointIndexStart + 1) % m_MaxTrailPoints;
                    m_PointIndexEnd               = newEndIndex;
                    m_PointTimes[m_PointIndexEnd] = 0;
                    m_LastPointTime               = m_PointTimes[m_PointIndexStart];
                }
            }

            m_Points[m_PointIndexEnd] = currentPoint;

            // Update the last recorded point
            m_LastRecordedPoint = currentPoint;
        }
        // Do time processing
        // The end point counts up to a maximum of 'time'
        m_PointTimes[m_PointIndexEnd] = Mathf.Min(m_PointTimes[m_PointIndexEnd] + deltaTime, m_Time);

        if (m_PointIndexStart != m_PointIndexEnd)
        {
            // Run down the counter on the start point
            m_PointTimes[m_PointIndexStart] -= deltaTime;

            // If we've hit 0, this point is done for
            if (m_PointTimes[m_PointIndexStart] <= 0.0f)
            {
                m_MeshData.SetElementSize(m_PointIndexStart * 2, 0);
                m_MeshData.SetElementSize((m_PointIndexStart * 2) + 1, 0);
                m_PointIndexStart = (m_PointIndexStart + 1) % m_MaxTrailPoints;
                m_LastPointTime   = m_PointTimes[m_PointIndexStart];
                m_UsedPoints--;
            }
        }

        if (m_PointIndexStart != m_PointIndexEnd)
        {
            m_MeshNeedsRefreshing  = true;
            m_MeshRenderer.enabled = true;
        }
        else
        {
            m_MeshNeedsRefreshing  = false;
            m_MeshRenderer.enabled = false;
        }
        if (m_MeshNeedsRefreshing == true)
        {
            m_MeshRenderer.enabled = true;

            // Update first and last points position-wise
            var nextIndex = (m_PointIndexStart + 1) % m_MaxTrailPoints;
            if (m_SmoothInterpolation)
            {
                var toNextPoint = 1.0f - (m_PointTimes[m_PointIndexStart] / m_LastPointTime);
                var lerpPoint   = Vector3.Lerp(m_Points[m_PointIndexStart], m_Points[nextIndex], toNextPoint);
                m_MeshData.SetElementPosition((m_PointIndexStart * 2), ref lerpPoint);
                m_MeshData.SetElementPipe((m_PointIndexStart * 2) + 1, ref lerpPoint, ref m_Points[nextIndex]);
            }
            else
            {
                m_MeshData.SetElementPosition((m_PointIndexStart * 2), ref m_Points[m_PointIndexStart]);
                m_MeshData.SetElementPipe((m_PointIndexStart * 2) + 1, ref m_Points[m_PointIndexStart], ref m_Points[nextIndex]);
            }

            var prevIndex = m_PointIndexEnd - 1;
            if (prevIndex < 0)
            {
                prevIndex = m_MaxTrailPoints - 1;
            }

            m_MeshData.SetElementPipe((prevIndex * 2) + 1, ref m_Points[prevIndex], ref m_Points[m_PointIndexEnd]);
            m_MeshData.SetElementPosition((m_PointIndexEnd * 2), ref m_Points[m_PointIndexEnd]);


            // Go through all points and update size and color
            var pointUpdateCounter = m_PointIndexStart;
            var pointCount         = 0;
            var blendStep          = 1.0f / m_UsedPoints;
            var colorValue         = 1.0f;

            while (pointUpdateCounter != m_PointIndexEnd)
            {
                var currentBlend = blendStep * pointCount;
                var nextBlend    = blendStep * (pointCount + 1.0f);

                var currentWidth = Mathf.Lerp(m_EndWidth, m_StartWidth, currentBlend);
                var nextWidth    = Mathf.Lerp(m_EndWidth, m_StartWidth, nextBlend);

                m_MeshData.SetElementSize(pointUpdateCounter * 2, currentWidth);
                m_MeshData.SetElementSize((pointUpdateCounter * 2) + 1, currentWidth, nextWidth);

                var currentColor = GetLerpedColor(colorValue);
                var nextColor    = GetLerpedColor(colorValue - blendStep);

                m_MeshData.SetElementColor(pointUpdateCounter * 2, ref currentColor);
                m_MeshData.SetElementColor((pointUpdateCounter * 2) + 1, ref currentColor, ref nextColor);

                pointUpdateCounter = (pointUpdateCounter + 1) % m_MaxTrailPoints;
                pointCount++;
                colorValue -= blendStep;
            }

            m_MeshData.SetElementSize((m_PointIndexEnd * 2), m_StartWidth);
            m_MeshData.SetElementColor((m_PointIndexEnd * 2), ref m_Colors[0]);

            m_MeshData.SetMeshDataDirty(VRLineRendererInternal.MeshChain.MeshRefreshFlag.All);

            m_MeshData.RefreshMesh();
        }
    }