Tanoda
LeapBakedRenderer.cs
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (C) Ultraleap, Inc. 2011-2020. *
3 * *
4 * Use subject to the terms of the Apache License 2.0 available at *
5 * http://www.apache.org/licenses/LICENSE-2.0, or another agreement *
6 * between Ultraleap and you, your company or other organization. *
7 ******************************************************************************/
8
9using System;
10using System.Collections.Generic;
11using UnityEngine;
12#if UNITY_EDITOR
13using UnityEditor;
14#endif
15using Leap.Unity.Space;
16using Leap.Unity.Query;
18
20
21 [LeapGraphicTag("Baked")]
22 [Serializable]
24
25 public const string DEFAULT_SHADER = "LeapMotion/GraphicRenderer/Unlit/Baked";
26
27 #region INSPECTOR FIELDS
28
29 #pragma warning disable 0649
30 [Tooltip("What type of graphic motion should be supported by this renderer? Currently there are only two modes, None, and Translation.")]
32 [SerializeField]
33 private MotionType _motionType = MotionType.Translation;
34
35 [Tooltip("Should the baked renderer create an actual game object and attach a mesh renderer to it in order to display the graphics?")]
37 [SerializeField]
38 private bool _createMeshRenderers;
39 #pragma warning restore 0649
40
41 #endregion
42
43 #region PRIVATE VARIABLES
44
45 [SerializeField, HideInInspector]
46 private List<MeshRendererContainer> _renderers = new List<MeshRendererContainer>();
47
48 //## Rect space
49 private const string RECT_POSITIONS = LeapGraphicRenderer.PROPERTY_PREFIX + "Rect_GraphicPositions";
50 private List<Vector4> _rect_graphicPositions = new List<Vector4>();
51
52 //## Cylindrical/Spherical spaces
53 private const string CURVED_PARAMETERS = LeapGraphicRenderer.PROPERTY_PREFIX + "Curved_GraphicParameters";
54 private List<Vector4> _curved_graphicParameters = new List<Vector4>();
55
56 //## Cache data to be used inside of graphicVertToMeshVert
57 private Matrix4x4 _translation_graphicVertToMeshVert;
58 private Matrix4x4 _noMotion_graphicVertToLocalVert;
59 private ITransformer _noMotion_transformer;
60
61 #endregion
62
63 public enum MotionType {
64 None,
65 Translation
66 }
67
68 public override SupportInfo GetSpaceSupportInfo(LeapSpace space) {
69 if (space == null ||
70 space is LeapCylindricalSpace ||
71 space is LeapSphericalSpace) {
72 return SupportInfo.FullSupport();
73 } else {
74 return SupportInfo.Error("Baked Renderer does not support " + space.GetType().Name);
75 }
76 }
77
78 public override void OnEnableRenderer() {
79 base.OnEnableRenderer();
80
81 foreach (var renderer in _renderers) {
82 renderer.ClearPropertyBlock();
83 }
84 }
85
86 public override void OnUpdateRenderer() {
87 using (new ProfilerSample("Update Baked Renderer")) {
88 base.OnUpdateRenderer();
89
90 if (_motionType != MotionType.None) {
91 if (renderer.space == null) {
92 using (new ProfilerSample("Build Material Data")) {
93 _rect_graphicPositions.Clear();
94 foreach (var graphic in group.graphics) {
95 Vector3 localSpace;
96 if (graphic.isActiveAndEnabled) {
97 localSpace = renderer.transform.InverseTransformPoint(graphic.transform.position);
98 } else {
99 localSpace = Vector3.one * float.NaN;
100 }
101
102 _rect_graphicPositions.Add(localSpace);
103 }
104 }
105
106 using (new ProfilerSample("Upload Material Data")) {
107 _material.SetVectorArraySafe(RECT_POSITIONS, _rect_graphicPositions);
108 }
109 } else if (renderer.space is LeapRadialSpace) {
110 var radialSpace = renderer.space as LeapRadialSpace;
111
112 using (new ProfilerSample("Build Material Data")) {
113 _curved_graphicParameters.Clear();
114 foreach (var graphic in group.graphics) {
115 var t = graphic.anchor.transformer as IRadialTransformer;
116 Vector4 vectorRepresentation;
117 if (graphic.isActiveAndEnabled) {
118 vectorRepresentation = t.GetVectorRepresentation(graphic.transform);
119 } else {
120 vectorRepresentation = Vector4.one * float.NaN;
121 }
122
123 _curved_graphicParameters.Add(vectorRepresentation);
124 }
125 }
126
127 using (new ProfilerSample("Upload Material Data")) {
128 _material.SetFloat(SpaceProperties.RADIAL_SPACE_RADIUS, radialSpace.radius);
129 _material.SetVectorArraySafe(CURVED_PARAMETERS, _curved_graphicParameters);
130 }
131 }
132 }
133
134 if (!_createMeshRenderers) {
135 using (new ProfilerSample("Draw Meshes")) {
136 for (int i = 0; i < _meshes.Count; i++) {
137 drawMesh(_meshes[i], renderer.transform.localToWorldMatrix);
138 }
139 }
140 }
141 }
142 }
143
144#if UNITY_EDITOR
145 public override void OnEnableRendererEditor() {
146 base.OnEnableRendererEditor();
147
148 _shader = Shader.Find(DEFAULT_SHADER);
149 }
150
151 public override void OnDisableRendererEditor() {
152 base.OnDisableRendererEditor();
153
154 foreach (var renderer in _renderers) {
155 renderer.Destroy();
156 }
157 _renderers.Clear();
158 }
159
160 public override void OnUpdateRendererEditor() {
161 base.OnUpdateRendererEditor();
162
163 if (_renderers == null) {
164 _renderers = new List<MeshRendererContainer>();
165 }
166
167 if (_createMeshRenderers) {
168 for (int i = _renderers.Count; i-- != 0;) {
169 if (_renderers[i].obj == null) {
170 _renderers.RemoveAt(i);
171 }
172 }
173
174 while (_renderers.Count > _meshes.Count) {
175 _renderers.RemoveLast().Destroy();
176 }
177
178 while (_renderers.Count < _meshes.Count) {
179 _renderers.Add(new MeshRendererContainer(renderer.transform));
180 }
181
182 for (int i = 0; i < _meshes.Count; i++) {
183 _renderers[i].MakeValid(renderer.transform, i, _meshes[i], _material, _spriteTextureBlock);
184 }
185 } else {
186 while (_renderers.Count > 0) {
187 _renderers.RemoveLast().Destroy();
188 }
189 }
190 }
191#endif
192
193 protected override void prepareMaterial() {
194 if (_shader == null) {
195 _shader = Shader.Find(DEFAULT_SHADER);
196 }
197
198 base.prepareMaterial();
199
200 switch (_motionType) {
201 case MotionType.Translation:
203 break;
204 }
205
206 if (_motionType != MotionType.None) {
208 _material.EnableKeyword(SpaceProperties.CYLINDRICAL_FEATURE);
209 } else if (renderer.space is LeapSphericalSpace) {
210 _material.EnableKeyword(SpaceProperties.SPHERICAL_FEATURE);
211 }
212 }
213 }
214
215 protected override void buildTopology() {
216 //If the next graphic is going to put us over the limit, finish the current mesh
217 //and start a new one.
218 if (_generation.verts.Count + _generation.graphic.mesh.vertexCount > MeshUtil.MAX_VERT_COUNT) {
220 beginMesh();
221 }
222
223 switch (_motionType) {
224 case MotionType.None:
225 _noMotion_transformer = _generation.graphic.transformer;
226 _noMotion_graphicVertToLocalVert = renderer.transform.worldToLocalMatrix *
227 _generation.graphic.transform.localToWorldMatrix;
228 break;
229 case MotionType.Translation:
230 _translation_graphicVertToMeshVert = Matrix4x4.TRS(-renderer.transform.InverseTransformPoint(_generation.graphic.transform.position),
231 Quaternion.identity,
232 Vector3.one) *
233 renderer.transform.worldToLocalMatrix *
234 _generation.graphic.transform.localToWorldMatrix;
235
236 break;
237 default:
238 throw new NotImplementedException();
239 }
240
241 base.buildTopology();
242 }
243
244 protected override void postProcessMesh() {
245 base.postProcessMesh();
246
247 //For the baked renderer, the mesh really never accurately represents it's visual position
248 //or size, so just disable culling entirely by making the bound gigantic.
249 _generation.mesh.bounds = new Bounds(Vector3.zero, Vector3.one * 100000);
250 }
251
252 protected override bool doesRequireVertInfo() {
253 if (_motionType != MotionType.None) {
254 return true;
255 }
256
257 return base.doesRequireVertInfo();
258 }
259
260 protected override Vector3 graphicVertToMeshVert(Vector3 vertex) {
261 switch (_motionType) {
262 case MotionType.None:
263 var localVert = _noMotion_graphicVertToLocalVert.MultiplyPoint3x4(vertex);
264 return _noMotion_transformer.TransformPoint(localVert);
265 case MotionType.Translation:
266 return _translation_graphicVertToMeshVert.MultiplyPoint3x4(vertex);
267 }
268
269 throw new NotImplementedException();
270 }
271
272 protected override void graphicVertNormalToMeshVertNormal(Vector3 vertex,
273 Vector3 normal,
274 out Vector3 meshVert,
275 out Vector3 meshNormal) {
276 switch (_motionType) {
277 case MotionType.None:
278 var localVert = _noMotion_graphicVertToLocalVert.MultiplyPoint3x4(vertex);
279 var localNormal = _noMotion_graphicVertToLocalVert.MultiplyVector(normal);
280 var matrix = _noMotion_transformer.GetTransformationMatrix(localVert);
281 meshVert = matrix.MultiplyPoint3x4(Vector3.zero);
282 meshNormal = matrix.MultiplyVector(localNormal);
283 return;
284 case MotionType.Translation:
285 meshVert = _translation_graphicVertToMeshVert.MultiplyPoint3x4(vertex);
286 meshNormal = _translation_graphicVertToMeshVert.MultiplyVector(normal);
287 return;
288 }
289
290 throw new NotImplementedException();
291 }
292
293 [Serializable]
294 protected class MeshRendererContainer {
295 public GameObject obj;
296 public MeshFilter filter;
297 public MeshRenderer renderer;
298
299 public MeshRendererContainer(Transform root) {
300 obj = new GameObject("Graphic Renderer");
301 obj.transform.SetParent(root);
302#if UNITY_EDITOR
303 Undo.RegisterCreatedObjectUndo(obj, "Created graphic renderer");
304#endif
305
306 filter = null;
307 renderer = null;
308 }
309
310 public void Destroy() {
311#if UNITY_EDITOR
312 if (!Application.isPlaying) {
313 Undo.DestroyObjectImmediate(obj);
314 } else
315#endif
316 {
317 UnityEngine.Object.Destroy(obj);
318 }
319 }
320
321 public void MakeValid(Transform root, int index, Mesh mesh, Material material, MaterialPropertyBlock block) {
322 obj.transform.SetParent(root);
323 obj.transform.SetSiblingIndex(index);
324 obj.SetActive(true);
325
326 obj.transform.localPosition = Vector3.zero;
327 obj.transform.localRotation = Quaternion.identity;
328 obj.transform.localScale = Vector3.one;
329
330 if (filter == null) {
331 filter = InternalUtility.AddComponent<MeshFilter>(obj);
332 }
333 filter.sharedMesh = mesh;
334
335 if (renderer == null) {
336 renderer = InternalUtility.AddComponent<MeshRenderer>(obj);
337 }
338 renderer.enabled = true;
339 renderer.sharedMaterial = material;
340 renderer.SetPropertyBlock(block);
341 }
342
343 public void ClearPropertyBlock() {
344 renderer.SetPropertyBlock(new MaterialPropertyBlock());
345 }
346 }
347 }
348}
void MakeValid(Transform root, int index, Mesh mesh, Material material, MaterialPropertyBlock block)
override void OnUpdateRenderer()
Called from LateUpdate during runtime. Use this to update the renderer using any changes made to duri...
override Vector3 graphicVertToMeshVert(Vector3 vertex)
override void OnEnableRenderer()
Called when the renderer is enabled at runtime.
override void graphicVertNormalToMeshVertNormal(Vector3 vertex, Vector3 normal, out Vector3 meshVert, out Vector3 meshNormal)
override SupportInfo GetSpaceSupportInfo(LeapSpace space)
List< LeapGraphic > graphics
Returns the list of graphics attached to this group. This getter returns a regular mutable list for s...
ITransformer transformer
A utility getter that returns a transformer for this graphic. Even if the space anchor for this graph...
Definition: LeapGraphic.cs:120
LeapSpace space
Returns the leap space that is currently attached to this graphic renderer.
Mesh mesh
Returns the mesh that represents this graphic. It can have any topology, any number of uv channels,...
virtual void finishAndAddMesh(bool deleteEmptyMeshes=true)
void drawMesh(Mesh mesh, Matrix4x4 transform)
virtual void beginMesh(Mesh mesh=null)
LeapGraphicGroup group
Gets the group this rendering method is attached to.
LeapGraphicRenderer renderer
Gets the renderer this rendering method is attached to.
Matrix4x4 GetTransformationMatrix(Vector3 localRectPos)
Get a transformation matrix that maps a position in rect space to a position in warped space.
Vector3 TransformPoint(Vector3 localRectPos)
Transform a point from rect space to warped space.
The support info class provides a very basic way to notify that something is fully supported,...
Definition: SupportInfo.cs:21
static SupportInfo Error(string message)
Helper getter to return a struct that signifies no support with an error message.
Definition: SupportInfo.cs:42
static SupportInfo FullSupport()
Helper getter to return a struct that signifies full support.
Definition: SupportInfo.cs:28
A utility struct for ease of use when you want to wrap a piece of code in a Profiler....