/// <summary> /// Creates or updates the underlying mesh data /// </summary> protected override void Initialize(bool setMesh = true) { base.Initialize(setMesh); m_MaxTrailPoints = Mathf.Max(m_MaxTrailPoints, 3); // If we already have the right amount of points and mesh, then we can get away with just clearing the curve out if (m_Points != null && m_MaxTrailPoints == m_Points.Length && m_XRMeshData != null) { Clear(); return; } m_Points = new Vector3[m_MaxTrailPoints]; m_PointTimes = new float[m_MaxTrailPoints]; // For a trail renderer we assume one big chain // We need a control point for each billboard and a control point for each pipe connecting them together // We make this a circular trail so the update logic is easier. This gives us (position * 2) var neededPoints = Mathf.Max((m_MaxTrailPoints * 2), 0); if (m_XRMeshData == null) { m_XRMeshData = new XRMeshChain(); } if (m_XRMeshData.reservedElements != neededPoints) { m_XRMeshData.worldSpaceData = true; m_XRMeshData.centerAtRoot = true; m_XRMeshData.GenerateMesh(gameObject, true, neededPoints, setMesh); if (neededPoints == 0) { return; } // Dirty all the VRMeshChain flags so everything gets refreshed m_MeshRenderer.enabled = false; m_XRMeshData.SetMeshDataDirty(XRMeshChain.MeshRefreshFlag.All); m_MeshNeedsRefreshing = true; } Clear(); }
/// <summary> /// Creates or updates the underlying mesh data /// </summary> protected override void Initialize(bool setMesh = true) { base.Initialize(); CopyWorldSpaceDataFromMaterial(); if (m_Positions == null) { m_Positions = new Vector3[0]; } // For a line renderer we assume one big chain // We need a control point for each billboard and a control point for each pipe connecting them together // Except for the end, which must be capped with another billboard. This gives us (positions * 2) - 1 // If we're looping, then we do need one more pipe var neededPoints = m_Loop ? 1 : 0; neededPoints = Mathf.Max(neededPoints + (m_Positions.Length * 2) - 1, 0); if (m_XRMeshData == null) { m_XRMeshData = new XRMeshChain(); } if (m_XRMeshData.reservedElements != neededPoints) { m_XRMeshData.worldSpaceData = useWorldSpace; m_XRMeshData.GenerateMesh(gameObject, true, neededPoints, setMesh); } // If we have no points, then just assume that stepping through a single point would take us through the whole line if (neededPoints == 0) { m_StepSize = 1.0f; return; } m_StepSize = 1.0f / Mathf.Max(m_Loop ? m_Positions.Length : m_Positions.Length - 1, 1.0f); var pointCounter = 0; var elementCounter = 0; var stepPercent = 0.0f; var lastColor = m_Color.Evaluate(stepPercent); var lastWidth = m_WidthCurve.Evaluate(stepPercent) * m_Width; // Initialize the single starting point m_XRMeshData.SetElementSize(elementCounter, lastWidth); m_XRMeshData.SetElementPosition(elementCounter, ref m_Positions[pointCounter]); m_XRMeshData.SetElementColor(elementCounter, ref lastColor); elementCounter++; pointCounter++; stepPercent += m_StepSize; // Now do the chain while (pointCounter < m_Positions.Length) { var currentWidth = m_WidthCurve.Evaluate(stepPercent) * m_Width; var currentColor = m_Color.Evaluate(stepPercent); // Create a pipe from the previous point to here m_XRMeshData.SetElementSize(elementCounter, lastWidth, currentWidth); m_XRMeshData.SetElementPipe(elementCounter, ref m_Positions[pointCounter - 1], ref m_Positions[pointCounter]); m_XRMeshData.SetElementColor(elementCounter, ref lastColor, ref currentColor); elementCounter++; // Now record our own point data m_XRMeshData.SetElementSize(elementCounter, currentWidth); m_XRMeshData.SetElementPosition(elementCounter, ref m_Positions[pointCounter]); m_XRMeshData.SetElementColor(elementCounter, ref currentColor); // Go onto the next point while retaining previous values we might need to lerp between lastWidth = currentWidth; lastColor = currentColor; elementCounter++; pointCounter++; stepPercent += m_StepSize; } if (m_Loop) { var currentWidth = m_WidthCurve.Evaluate(stepPercent) * m_Width; var currentColor = m_Color.Evaluate(stepPercent); m_XRMeshData.SetElementSize(elementCounter, lastWidth, currentWidth); m_XRMeshData.SetElementPipe(elementCounter, ref m_Positions[pointCounter - 1], ref m_Positions[0]); m_XRMeshData.SetElementColor(elementCounter, ref lastColor, ref currentColor); } // Dirty all the VRMeshChain flags so everything gets refreshed m_XRMeshData.SetMeshDataDirty(XRMeshChain.MeshRefreshFlag.All); m_MeshNeedsRefreshing = true; }