209 lines
7.2 KiB
C#
209 lines
7.2 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
namespace Microsoft.MixedReality.Toolkit.Utilities
|
|
{
|
|
/// <summary>
|
|
/// Draws a strip of polygons along the line
|
|
/// </summary>
|
|
[AddComponentMenu("Scripts/MRTK/Core/StripMeshLineRenderer")]
|
|
public class StripMeshLineRenderer : BaseMixedRealityLineRenderer
|
|
{
|
|
[Header("Strip Mesh Settings")]
|
|
|
|
[SerializeField]
|
|
private Material lineMaterial = null;
|
|
[SerializeField]
|
|
private float uvOffset = 0f;
|
|
|
|
[SerializeField]
|
|
[HideInInspector]
|
|
private MeshRenderer stripMeshRenderer;
|
|
[SerializeField]
|
|
[HideInInspector]
|
|
private GameObject meshRendererGameObject;
|
|
|
|
private Mesh stripMesh;
|
|
private Material lineMatInstance;
|
|
|
|
private readonly List<Vector3> positions = new List<Vector3>();
|
|
private readonly List<Vector3> forwards = new List<Vector3>();
|
|
private readonly List<Color> colors = new List<Color>();
|
|
private readonly List<float> widths = new List<float>();
|
|
|
|
private static Vector3[] stripMeshVertices = null;
|
|
private static Color[] stripMeshColors = null;
|
|
private static Vector2[] stripMeshUvs = null;
|
|
private static int[] stripMeshTriangles = null;
|
|
|
|
private void OnEnable()
|
|
{
|
|
if (lineMaterial == null)
|
|
{
|
|
Debug.LogError("LineDataProvider material cannot be null.");
|
|
enabled = false;
|
|
return;
|
|
}
|
|
|
|
lineMatInstance = new Material(lineMaterial);
|
|
|
|
// Create a mesh
|
|
if (stripMesh == null)
|
|
{
|
|
stripMesh = new Mesh();
|
|
}
|
|
|
|
if (stripMeshRenderer == null)
|
|
{
|
|
meshRendererGameObject = new GameObject("Strip Mesh Renderer");
|
|
stripMeshRenderer = meshRendererGameObject.AddComponent<MeshRenderer>();
|
|
}
|
|
|
|
stripMeshRenderer.sharedMaterial = lineMatInstance;
|
|
stripMeshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
|
|
stripMeshRenderer.receiveShadows = false;
|
|
stripMeshRenderer.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
|
|
|
|
var stripMeshFilter = stripMeshRenderer.EnsureComponent<MeshFilter>();
|
|
stripMeshFilter.sharedMesh = stripMesh;
|
|
}
|
|
|
|
private void OnDisable()
|
|
{
|
|
if (lineMatInstance != null)
|
|
{
|
|
if (Application.isEditor)
|
|
{
|
|
DestroyImmediate(lineMatInstance);
|
|
}
|
|
else
|
|
{
|
|
Destroy(lineMatInstance);
|
|
}
|
|
}
|
|
|
|
if (meshRendererGameObject != null)
|
|
{
|
|
if (Application.isEditor)
|
|
{
|
|
DestroyImmediate(meshRendererGameObject);
|
|
}
|
|
else
|
|
{
|
|
Destroy(meshRendererGameObject);
|
|
}
|
|
stripMeshRenderer = null;
|
|
}
|
|
}
|
|
|
|
/// <inheritdoc />
|
|
protected override void UpdateLine()
|
|
{
|
|
if (stripMeshRenderer == null)
|
|
{
|
|
Debug.LogError("Strip mesh renderer has been destroyed - disabling");
|
|
enabled = false;
|
|
}
|
|
|
|
if (!LineDataSource.enabled)
|
|
{
|
|
stripMeshRenderer.enabled = false;
|
|
return;
|
|
}
|
|
|
|
stripMeshRenderer.enabled = true;
|
|
positions.Clear();
|
|
forwards.Clear();
|
|
colors.Clear();
|
|
widths.Clear();
|
|
|
|
for (int i = 0; i <= LineStepCount; i++)
|
|
{
|
|
float normalizedDistance = GetNormalizedPointAlongLine(i);
|
|
positions.Add(LineDataSource.GetPoint(normalizedDistance));
|
|
colors.Add(GetColor(normalizedDistance));
|
|
widths.Add(GetWidth(normalizedDistance));
|
|
forwards.Add(LineDataSource.GetVelocity(normalizedDistance));
|
|
}
|
|
|
|
GenerateStripMesh(positions, colors, widths, uvOffset, forwards, stripMesh, LineDataSource.LineTransform.up);
|
|
}
|
|
|
|
public static void GenerateStripMesh(List<Vector3> positionList, List<Color> colorList, List<float> thicknessList, float uvOffsetLocal, List<Vector3> forwardList, Mesh mesh, Vector3 up)
|
|
{
|
|
int vertexCount = positionList.Count * 2;
|
|
int colorCount = colorList.Count * 2;
|
|
int uvCount = positionList.Count * 2;
|
|
|
|
if (stripMeshVertices == null || stripMeshVertices.Length != vertexCount)
|
|
{
|
|
stripMeshVertices = new Vector3[vertexCount];
|
|
}
|
|
|
|
if (stripMeshColors == null || stripMeshColors.Length != colorCount)
|
|
{
|
|
stripMeshColors = new Color[colorCount];
|
|
}
|
|
|
|
if (stripMeshUvs == null || stripMeshUvs.Length != uvCount)
|
|
{
|
|
stripMeshUvs = new Vector2[uvCount];
|
|
}
|
|
|
|
for (int x = 0; x < positionList.Count; x++)
|
|
{
|
|
int index = (int)(x * 0.5f);
|
|
Vector3 forward = forwardList[index];
|
|
Vector3 right = Vector3.Cross(forward, up).normalized;
|
|
float thickness = thicknessList[index] * 0.5f;
|
|
stripMeshVertices[2 * x] = positionList[x] - right * thickness;
|
|
stripMeshVertices[2 * x + 1] = positionList[x] + right * thickness;
|
|
stripMeshColors[2 * x] = colorList[x];
|
|
stripMeshColors[2 * x + 1] = colorList[x];
|
|
|
|
float uv = uvOffsetLocal;
|
|
|
|
if (x == positionList.Count - 1 && x > 1)
|
|
{
|
|
float distLast = (positionList[x - 2] - positionList[x - 1]).magnitude;
|
|
float distCur = (positionList[x] - positionList[x - 1]).magnitude;
|
|
uv += 1 - distCur / distLast;
|
|
}
|
|
|
|
stripMeshUvs[2 * x] = new Vector2(0, x - uv);
|
|
stripMeshUvs[2 * x + 1] = new Vector2(1, x - uv);
|
|
}
|
|
|
|
int numTriangles = ((positionList.Count * 2 - 2) * 3);
|
|
|
|
if (stripMeshTriangles == null || stripMeshTriangles.Length != numTriangles)
|
|
{
|
|
stripMeshTriangles = new int[numTriangles];
|
|
}
|
|
|
|
int j = 0;
|
|
|
|
for (int i = 0; i < positionList.Count * 2 - 3; i += 2, j++)
|
|
{
|
|
stripMeshTriangles[i * 3] = j * 2;
|
|
stripMeshTriangles[i * 3 + 1] = j * 2 + 1;
|
|
stripMeshTriangles[i * 3 + 2] = j * 2 + 2;
|
|
|
|
stripMeshTriangles[i * 3 + 3] = j * 2 + 1;
|
|
stripMeshTriangles[i * 3 + 4] = j * 2 + 3;
|
|
stripMeshTriangles[i * 3 + 5] = j * 2 + 2;
|
|
}
|
|
|
|
mesh.Clear();
|
|
mesh.vertices = stripMeshVertices;
|
|
mesh.uv = stripMeshUvs;
|
|
mesh.triangles = stripMeshTriangles;
|
|
mesh.colors = stripMeshColors;
|
|
mesh.RecalculateBounds();
|
|
mesh.RecalculateNormals();
|
|
}
|
|
}
|
|
} |