AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
LineStripMesh.cs
Go to the documentation of this file.
1 // Copyright (c) Microsoft Corporation. All rights reserved.
2 // Licensed under the MIT License. See LICENSE in the project root for license information.
3 
4 using HoloToolkit.Unity;
5 using System.Collections.Generic;
6 using UnityEngine;
7 
8 namespace HoloToolkit.Unity.UX
9 {
10  [UseWith(typeof(LineBase))]
12  {
13  [Header("Strip Mesh Settings")]
14  public Material LineMaterial;
15 
16  public Vector3 Forward;
17 
18  [SerializeField]
19  private float uvOffset = 0f;
20 
21  private Mesh stripMesh;
22  private MeshRenderer stripMeshRenderer;
23  private Material lineMatInstance;
24  private List<Vector3> positions = new List<Vector3>();
25  private List<Vector3> forwards = new List<Vector3>();
26  private List<Color> colors = new List<Color>();
27  private List<float> widths = new List<float>();
28 
29  private GameObject meshRendererGameObject;
30 
31  protected void OnEnable()
32  {
33  if (LineMaterial == null)
34  {
35  Debug.LogError("Line material cannot be null.");
36  enabled = false;
37  return;
38  }
39 
40  lineMatInstance = new Material(LineMaterial);
41 
42  // Create a mesh
43  if (stripMesh == null)
44  {
45  stripMesh = new Mesh();
46  }
47 
48  if (stripMeshRenderer == null)
49  {
50  meshRendererGameObject = new GameObject("Strip Mesh Renderer");
51  stripMeshRenderer = meshRendererGameObject.AddComponent<MeshRenderer>();
52  }
53 
54  stripMeshRenderer.sharedMaterial = lineMatInstance;
55  stripMeshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off;
56  stripMeshRenderer.receiveShadows = false;
57  stripMeshRenderer.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off;
58 
59  MeshFilter stripMeshFilter = stripMeshRenderer.EnsureComponent<MeshFilter>();
60  stripMeshFilter.sharedMesh = stripMesh;
61  }
62 
63  private void OnDisable()
64  {
65  if (lineMatInstance != null)
66  {
67  GameObject.Destroy(lineMatInstance);
68  }
69 
70  if (meshRendererGameObject != null)
71  {
72  GameObject.Destroy(meshRendererGameObject);
73  stripMeshRenderer = null;
74  }
75  }
76 
77  public void Update()
78  {
79  if (!Source.enabled)
80  {
81  stripMeshRenderer.enabled = false;
82  return;
83  }
84 
85  stripMeshRenderer.enabled = true;
86  positions.Clear();
87  forwards.Clear();
88  colors.Clear();
89  widths.Clear();
90 
91  for (int i = 0; i <= NumLineSteps; i++)
92  {
93  float normalizedDistance = (1f / (NumLineSteps - 1)) * i;
94  positions.Add(Source.GetPoint(normalizedDistance));
95  colors.Add(GetColor(normalizedDistance));
96  widths.Add(GetWidth(normalizedDistance));
97  forwards.Add(Source.GetRotation(normalizedDistance) * Vector3.down);
98  }
99 
100  GenerateStripMesh(positions, colors, widths, uvOffset, forwards, stripMesh);
101  }
102 
103  public static void GenerateStripMesh(List<Vector3> positionList, List<Color> colorList, List<float> thicknessList, float uvOffsetLocal, List<Vector3> forwardList, Mesh mesh)
104  {
105  int vertexCount = positionList.Count * 2;
106  int colorCount = colorList.Count * 2;
107  int uvCount = positionList.Count * 2;
108 
109  if (stripMeshVertices == null || stripMeshVertices.Length != vertexCount)
110  {
111  stripMeshVertices = new Vector3[vertexCount];
112  }
113  if (stripMeshColors == null || stripMeshColors.Length != colorCount)
114  {
115  stripMeshColors = new Color[colorCount];
116  }
117  if (stripMeshUvs == null || stripMeshUvs.Length != uvCount)
118  {
119  stripMeshUvs = new Vector2[uvCount];
120  }
121 
122  for (int x = 0; x < positionList.Count; x++)
123  {
124  Vector3 forward = forwardList[x / 2];
125  Vector3 right = Vector3.Cross(forward, Vector3.up).normalized;
126  float thickness = thicknessList[x / 2] / 2;
127  stripMeshVertices[2 * x] = positionList[x] - right * thickness;
128  stripMeshVertices[2 * x + 1] = positionList[x] + right * thickness;
129  stripMeshColors[2 * x] = colorList[x];
130  stripMeshColors[2 * x + 1] = colorList[x];
131 
132  float uv = uvOffsetLocal;
133  if (x == positionList.Count - 1 && x > 1)
134  {
135  float dist_last = (positionList[x - 2] - positionList[x - 1]).magnitude;
136  float dist_cur = (positionList[x] - positionList[x - 1]).magnitude;
137  uv += 1 - dist_cur / dist_last;
138  }
139 
140  stripMeshUvs[2 * x] = new Vector2(0, x - uv);
141  stripMeshUvs[2 * x + 1] = new Vector2(1, x - uv);
142  }
143 
144  int numTriangles = ((positionList.Count * 2 - 2) * 3);
145  if (stripMeshTriangles == null || stripMeshTriangles.Length != numTriangles)
146  {
147  stripMeshTriangles = new int[numTriangles];
148  }
149  int j = 0;
150  for (int i = 0; i < positionList.Count * 2 - 3; i += 2, j++)
151  {
152  stripMeshTriangles[i * 3] = j * 2;
153  stripMeshTriangles[i * 3 + 1] = j * 2 + 1;
154  stripMeshTriangles[i * 3 + 2] = j * 2 + 2;
155 
156  stripMeshTriangles[i * 3 + 3] = j * 2 + 1;
157  stripMeshTriangles[i * 3 + 4] = j * 2 + 3;
158  stripMeshTriangles[i * 3 + 5] = j * 2 + 2;
159  }
160 
161  mesh.Clear();
162  mesh.vertices = stripMeshVertices;
163  mesh.uv = stripMeshUvs;
164  mesh.triangles = stripMeshTriangles;
165  mesh.colors = stripMeshColors;
166  mesh.RecalculateBounds();
167  mesh.RecalculateNormals();
168  }
169 
170  private static Vector3[] stripMeshVertices = null;
171  private static Color[] stripMeshColors = null;
172  private static Vector2[] stripMeshUvs = null;
173  private static int[] stripMeshTriangles = null;
174 
175 #if UNITY_EDITOR
176  [UnityEditor.CustomEditor(typeof(LineStripMesh))]
177  public class CustomEditor : MRTKEditor { }
178 #endif
179  }
180 }
static void GenerateStripMesh(List< Vector3 > positionList, List< Color > colorList, List< float > thicknessList, float uvOffsetLocal, List< Vector3 > forwardList, Mesh mesh)