AR Design
UBC EML collab with UBC SALA - visualizing IoT data in AR
SchemaExtensions.cs
Go to the documentation of this file.
1 using GLTF;
2 using GLTF.Schema;
3 using UnityEngine;
4 
5 namespace UnityGLTF.Extensions
6 {
7  public static class SchemaExtensions
8  {
9  // glTF matrix: column vectors, column-major storage, +Y up, +Z forward, -X right, right-handed
10  // unity matrix: column vectors, column-major storage, +Y up, +Z forward, +X right, left-handed
11  // multiply by a negative X scale to convert handedness
12  public static readonly GLTF.Math.Vector3 CoordinateSpaceConversionScale = new GLTF.Math.Vector3(-1, 1, 1);
13  public static bool CoordinateSpaceConversionRequiresHandednessFlip
14  {
15  get
16  {
17  return CoordinateSpaceConversionScale.X * CoordinateSpaceConversionScale.Y * CoordinateSpaceConversionScale.Z < 0.0f;
18  }
19  }
20 
21  public static readonly GLTF.Math.Vector4 TangentSpaceConversionScale = new GLTF.Math.Vector4(-1, 1, 1, -1);
22 
30  public static void GetUnityTRSProperties(this Node node, out Vector3 position, out Quaternion rotation,
31  out Vector3 scale)
32  {
33  if (!node.UseTRS)
34  {
35  Matrix4x4 unityMat = node.Matrix.ToUnityMatrix4x4Convert();
36  unityMat.GetTRSProperties(out position, out rotation, out scale);
37  }
38  else
39  {
40  position = node.Translation.ToUnityVector3Convert();
41  rotation = node.Rotation.ToUnityQuaternionConvert();
42  scale = node.Scale.ToUnityVector3Raw();
43  }
44  }
45 
51  public static void SetUnityTransform(this Node node, Transform transform)
52  {
53  node.Translation = transform.localPosition.ToGltfVector3Convert();
54  node.Rotation = transform.localRotation.ToGltfQuaternionConvert();
55  node.Scale = transform.localScale.ToGltfVector3Raw();
56  }
57 
58  // todo: move to utility class
66  public static void GetTRSProperties(this Matrix4x4 mat, out Vector3 position, out Quaternion rotation,
67  out Vector3 scale)
68  {
69  position = mat.GetColumn(3);
70 
71  Vector3 x = mat.GetColumn(0);
72  Vector3 y = mat.GetColumn(1);
73  Vector3 z = mat.GetColumn(2);
74  Vector3 calculatedZ = Vector3.Cross(x, y);
75  bool mirrored = Vector3.Dot(calculatedZ, z) < 0.0f;
76 
77  scale = new Vector3(x.magnitude * (mirrored ? -1.0f : 1.0f), y.magnitude, z.magnitude);
78 
79  rotation = Quaternion.LookRotation(mat.GetColumn(2), mat.GetColumn(1));
80  }
81 
89  public static void GetTRSProperties(this GLTF.Math.Matrix4x4 gltfMat, out Vector3 position, out Quaternion rotation,
90  out Vector3 scale)
91  {
92  gltfMat.ToUnityMatrix4x4Convert().GetTRSProperties(out position, out rotation, out scale);
93  }
94 
101  public static GLTF.Math.Vector4 GetColumn(this GLTF.Math.Matrix4x4 mat, uint columnNum)
102  {
103  switch (columnNum)
104  {
105  case 0:
106  {
107  return new GLTF.Math.Vector4(mat.M11, mat.M21, mat.M31, mat.M41);
108  }
109  case 1:
110  {
111  return new GLTF.Math.Vector4(mat.M12, mat.M22, mat.M32, mat.M42);
112  }
113  case 2:
114  {
115  return new GLTF.Math.Vector4(mat.M13, mat.M23, mat.M33, mat.M43);
116  }
117  case 3:
118  {
119  return new GLTF.Math.Vector4(mat.M14, mat.M24, mat.M34, mat.M44);
120  }
121  default:
122  throw new System.Exception("column num is out of bounds");
123  }
124  }
125 
131  public static Quaternion ToUnityQuaternionConvert(this GLTF.Math.Quaternion gltfQuat)
132  {
133  // get raw matrix conversion (gltf matrix stored in a unity matrix for easier math)
134  Vector3 origAxis = new Vector3(gltfQuat.X, gltfQuat.Y, gltfQuat.Z);
135  float axisFlipScale = CoordinateSpaceConversionRequiresHandednessFlip ? -1.0f : 1.0f;
136  Vector3 newAxis = axisFlipScale * Vector3.Scale(origAxis, CoordinateSpaceConversionScale.ToUnityVector3Raw());
137 
138  // then put the quaternion back together and return it
139  return new Quaternion(newAxis.x, newAxis.y, newAxis.z, gltfQuat.W);
140  }
141 
147  public static GLTF.Math.Quaternion ToGltfQuaternionConvert(this Quaternion unityQuat)
148  {
149  // get the original axis and apply conversion scale as well as potential rotation axis flip
150  Vector3 origAxis = new Vector3(unityQuat.x, unityQuat.y, unityQuat.z);
151  float axisFlipScale = CoordinateSpaceConversionRequiresHandednessFlip ? -1.0f : 1.0f;
152  Vector3 newAxis = axisFlipScale * Vector3.Scale(origAxis, CoordinateSpaceConversionScale.ToUnityVector3Raw());
153 
154  // then put the quaternion back together and return it
155  return new GLTF.Math.Quaternion(newAxis.x, newAxis.y, newAxis.z, unityQuat.w);
156  }
157 
163  public static Matrix4x4 ToUnityMatrix4x4Convert(this GLTF.Math.Matrix4x4 gltfMat)
164  {
165  Matrix4x4 rawUnityMat = gltfMat.ToUnityMatrix4x4Raw();
166  Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
167  Matrix4x4 convert = Matrix4x4.Scale(coordinateSpaceConversionScale);
168  Matrix4x4 unityMat = convert * rawUnityMat * convert;
169  return unityMat;
170  }
171 
177  public static GLTF.Math.Matrix4x4 ToGltfMatrix4x4Convert(this Matrix4x4 unityMat)
178  {
179  Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
180  Matrix4x4 convert = Matrix4x4.Scale(coordinateSpaceConversionScale);
181  GLTF.Math.Matrix4x4 gltfMat = (convert * unityMat * convert).ToGltfMatrix4x4Raw();
182  return gltfMat;
183  }
184 
190  public static Vector3 ToUnityVector3Convert(this GLTF.Math.Vector3 gltfVec3)
191  {
192  Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
193  Vector3 unityVec3 = Vector3.Scale(gltfVec3.ToUnityVector3Raw(), coordinateSpaceConversionScale);
194  return unityVec3;
195  }
196 
202  public static GLTF.Math.Vector3 ToGltfVector3Convert(this Vector3 unityVec3)
203  {
204  Vector3 coordinateSpaceConversionScale = CoordinateSpaceConversionScale.ToUnityVector3Raw();
205  GLTF.Math.Vector3 gltfVec3 = Vector3.Scale(unityVec3, coordinateSpaceConversionScale).ToGltfVector3Raw();
206  return gltfVec3;
207  }
208 
209  public static GLTF.Math.Vector3 ToGltfVector3Raw(this Vector3 unityVec3)
210  {
211  GLTF.Math.Vector3 gltfVec3 = new GLTF.Math.Vector3(unityVec3.x, unityVec3.y, unityVec3.z);
212  return gltfVec3;
213  }
214 
215  public static GLTF.Math.Vector4 ToGltfVector4Raw(this Vector4 unityVec4)
216  {
217  GLTF.Math.Vector4 gltfVec4 = new GLTF.Math.Vector4(unityVec4.x, unityVec4.y, unityVec4.z, unityVec4.w);
218  return gltfVec4;
219  }
220 
221  public static Matrix4x4 ToUnityMatrix4x4Raw(this GLTF.Math.Matrix4x4 gltfMat)
222  {
223  Vector4 rawUnityCol0 = gltfMat.GetColumn(0).ToUnityVector4Raw();
224  Vector4 rawUnityCol1 = gltfMat.GetColumn(1).ToUnityVector4Raw();
225  Vector4 rawUnityCol2 = gltfMat.GetColumn(2).ToUnityVector4Raw();
226  Vector4 rawUnityCol3 = gltfMat.GetColumn(3).ToUnityVector4Raw();
227  Matrix4x4 rawUnityMat = new UnityEngine.Matrix4x4();
228  rawUnityMat.SetColumn(0, rawUnityCol0);
229  rawUnityMat.SetColumn(1, rawUnityCol1);
230  rawUnityMat.SetColumn(2, rawUnityCol2);
231  rawUnityMat.SetColumn(3, rawUnityCol3);
232 
233  return rawUnityMat;
234  }
235 
236  public static GLTF.Math.Matrix4x4 ToGltfMatrix4x4Raw(this Matrix4x4 unityMat)
237  {
238  GLTF.Math.Vector4 c0 = unityMat.GetColumn(0).ToGltfVector4Raw();
239  GLTF.Math.Vector4 c1 = unityMat.GetColumn(1).ToGltfVector4Raw();
240  GLTF.Math.Vector4 c2 = unityMat.GetColumn(2).ToGltfVector4Raw();
241  GLTF.Math.Vector4 c3 = unityMat.GetColumn(3).ToGltfVector4Raw();
242  GLTF.Math.Matrix4x4 rawGltfMat = new GLTF.Math.Matrix4x4(c0.X, c0.Y, c0.Z, c0.W, c1.X, c1.Y, c1.Z, c1.W, c2.X, c2.Y, c2.Z, c2.W, c3.X, c3.Y, c3.Z, c3.W);
243  return rawGltfMat;
244  }
245 
246  public static Vector2 ToUnityVector2Raw(this GLTF.Math.Vector2 vec2)
247  {
248  return new Vector2(vec2.X, vec2.Y);
249  }
250 
251  public static Vector2[] ToUnityVector2Raw(this GLTF.Math.Vector2[] inVecArr)
252  {
253  Vector2[] outVecArr = new Vector2[inVecArr.Length];
254  for (int i = 0; i < inVecArr.Length; ++i)
255  {
256  outVecArr[i] = inVecArr[i].ToUnityVector2Raw();
257  }
258  return outVecArr;
259  }
260 
261  public static Vector3 ToUnityVector3Raw(this GLTF.Math.Vector3 vec3)
262  {
263  return new Vector3(vec3.X, vec3.Y, vec3.Z);
264  }
265 
266  public static Vector3[] ToUnityVector3Raw(this GLTF.Math.Vector3[] inVecArr)
267  {
268  Vector3[] outVecArr = new Vector3[inVecArr.Length];
269  for (int i = 0; i < inVecArr.Length; ++i)
270  {
271  outVecArr[i] = inVecArr[i].ToUnityVector3Raw();
272  }
273  return outVecArr;
274  }
275 
276  public static Vector4 ToUnityVector4Raw(this GLTF.Math.Vector4 vec4)
277  {
278  return new Vector4(vec4.X, vec4.Y, vec4.Z, vec4.W);
279  }
280 
281  public static Vector4[] ToUnityVector4Raw(this GLTF.Math.Vector4[] inVecArr)
282  {
283  Vector4[] outVecArr = new Vector4[inVecArr.Length];
284  for (int i = 0; i < inVecArr.Length; ++i)
285  {
286  outVecArr[i] = inVecArr[i].ToUnityVector4Raw();
287  }
288  return outVecArr;
289  }
290 
291  public static UnityEngine.Color ToUnityColorRaw(this GLTF.Math.Color color)
292  {
293  return new UnityEngine.Color(color.R, color.G, color.B, color.A);
294  }
295 
296  public static GLTF.Math.Color ToNumericsColorRaw(this UnityEngine.Color color)
297  {
298  return new GLTF.Math.Color(color.r, color.g, color.b, color.a);
299  }
300 
301  public static UnityEngine.Color[] ToUnityColorRaw(this GLTF.Math.Color[] inColorArr)
302  {
303  UnityEngine.Color[] outColorArr = new UnityEngine.Color[inColorArr.Length];
304  for (int i = 0; i < inColorArr.Length; ++i)
305  {
306  outColorArr[i] = inColorArr[i].ToUnityColorRaw();
307  }
308  return outColorArr;
309  }
310 
311  public static int[] ToIntArrayRaw(this uint[] uintArr)
312  {
313  int[] intArr = new int[uintArr.Length];
314  for (int i = 0; i < uintArr.Length; ++i)
315  {
316  uint uintVal = uintArr[i];
317  Debug.Assert(uintVal <= int.MaxValue);
318  intArr[i] = (int)uintVal;
319  }
320 
321  return intArr;
322  }
323 
324  public static GLTF.Math.Quaternion ToGltfQuaternionRaw(this Quaternion unityQuat)
325  {
326  return new GLTF.Math.Quaternion(unityQuat.x, unityQuat.y, unityQuat.z, unityQuat.w);
327  }
328 
329  public static Quaternion ToUnityQuaternionRaw(this GLTF.Math.Quaternion quaternion)
330  {
331  return new Quaternion(quaternion.X, quaternion.Y, quaternion.Z, quaternion.W);
332  }
333 
338  public static void FlipTexCoordArrayV(ref AttributeAccessor attributeAccessor)
339  {
340  for (var i = 0; i < attributeAccessor.AccessorContent.AsVec2s.Length; i++)
341  {
342  attributeAccessor.AccessorContent.AsVec2s[i].Y = 1.0f - attributeAccessor.AccessorContent.AsVec2s[i].Y;
343  }
344  }
345 
351  public static UnityEngine.Vector2[] FlipTexCoordArrayVAndCopy(UnityEngine.Vector2[] array)
352  {
353  var returnArray = new UnityEngine.Vector2[array.Length];
354 
355  for (var i = 0; i < array.Length; i++)
356  {
357  returnArray[i].x = array[i].x;
358  returnArray[i].y = 1.0f - array[i].y;
359  }
360 
361  return returnArray;
362  }
363 
369  public static void ConvertVector3CoordinateSpace(ref AttributeAccessor attributeAccessor, GLTF.Math.Vector3 coordinateSpaceCoordinateScale)
370  {
371  for (int i = 0; i < attributeAccessor.AccessorContent.AsVertices.Length; i++)
372  {
373  attributeAccessor.AccessorContent.AsVertices[i].X *= coordinateSpaceCoordinateScale.X;
374  attributeAccessor.AccessorContent.AsVertices[i].Y *= coordinateSpaceCoordinateScale.Y;
375  attributeAccessor.AccessorContent.AsVertices[i].Z *= coordinateSpaceCoordinateScale.Z;
376  }
377  }
378 
385  public static UnityEngine.Vector3[] ConvertVector3CoordinateSpaceAndCopy(Vector3[] array, GLTF.Math.Vector3 coordinateSpaceCoordinateScale)
386  {
387  var returnArray = new UnityEngine.Vector3[array.Length];
388 
389  for (int i = 0; i < array.Length; i++)
390  {
391  returnArray[i].x = array[i].x * coordinateSpaceCoordinateScale.X;
392  returnArray[i].y = array[i].z * coordinateSpaceCoordinateScale.Y;
393  returnArray[i].z = array[i].y * coordinateSpaceCoordinateScale.Z;
394  }
395 
396  return returnArray;
397  }
398 
404  public static void ConvertVector4CoordinateSpace(ref AttributeAccessor attributeAccessor, GLTF.Math.Vector4 coordinateSpaceCoordinateScale)
405  {
406  for (int i = 0; i < attributeAccessor.AccessorContent.AsVec4s.Length; i++)
407  {
408  attributeAccessor.AccessorContent.AsVec4s[i].X *= coordinateSpaceCoordinateScale.X;
409  attributeAccessor.AccessorContent.AsVec4s[i].Y *= coordinateSpaceCoordinateScale.Y;
410  attributeAccessor.AccessorContent.AsVec4s[i].Z *= coordinateSpaceCoordinateScale.Z;
411  attributeAccessor.AccessorContent.AsVec4s[i].W *= coordinateSpaceCoordinateScale.W;
412  }
413  }
414 
421  public static Vector4[] ConvertVector4CoordinateSpaceAndCopy(Vector4[] array, GLTF.Math.Vector4 coordinateSpaceCoordinateScale)
422  {
423  var returnArray = new Vector4[array.Length];
424 
425  for (var i = 0; i < array.Length; i++)
426  {
427  returnArray[i].x *= coordinateSpaceCoordinateScale.X;
428  returnArray[i].y *= coordinateSpaceCoordinateScale.Y;
429  returnArray[i].z *= coordinateSpaceCoordinateScale.Z;
430  returnArray[i].w *= coordinateSpaceCoordinateScale.W;
431  }
432 
433  return returnArray;
434  }
435 
440  public static void FlipFaces(ref AttributeAccessor attributeAccessor)
441  {
442  for (int i = 0; i < attributeAccessor.AccessorContent.AsTriangles.Length; i += 3)
443  {
444  uint temp = attributeAccessor.AccessorContent.AsUInts[i];
445  attributeAccessor.AccessorContent.AsUInts[i] = attributeAccessor.AccessorContent.AsUInts[i + 2];
446  attributeAccessor.AccessorContent.AsUInts[i + 2] = temp;
447  }
448  }
449 
455  public static int[] FlipFacesAndCopy(int[] triangles)
456  {
457  int[] returnArr = new int[triangles.Length];
458  for (int i = 0; i < triangles.Length; i += 3)
459  {
460  int temp = triangles[i];
461  returnArr[i] = triangles[i + 2];
462  returnArr[i + 1] = triangles[i + 1];
463  returnArr[i + 2] = temp;
464  }
465 
466  return returnArr;
467  }
468  }
469 }
static Vector2 ToUnityVector2Raw(this GLTF.Math.Vector2 vec2)
static GLTF.Math.Color ToNumericsColorRaw(this UnityEngine.Color color)
static void ConvertVector3CoordinateSpace(ref AttributeAccessor attributeAccessor, GLTF.Math.Vector3 coordinateSpaceCoordinateScale)
Converts vector3 to specified coordinate space
static GLTF.Math.Quaternion ToGltfQuaternionConvert(this Quaternion unityQuat)
Convert unity quaternion to a gltf quaternion
static int [] ToIntArrayRaw(this uint[] uintArr)
static Quaternion ToUnityQuaternionConvert(this GLTF.Math.Quaternion gltfQuat)
Convert gltf quaternion to a unity quaternion
static Vector4 [] ToUnityVector4Raw(this GLTF.Math.Vector4[] inVecArr)
static Matrix4x4 ToUnityMatrix4x4Convert(this GLTF.Math.Matrix4x4 gltfMat)
Convert gltf matrix to a unity matrix
static Vector2 [] ToUnityVector2Raw(this GLTF.Math.Vector2[] inVecArr)
static UnityEngine.Color ToUnityColorRaw(this GLTF.Math.Color color)
static void GetTRSProperties(this Matrix4x4 mat, out Vector3 position, out Quaternion rotation, out Vector3 scale)
Get unity translation, rotation, and scale from a unity matrix
static Vector3 ToUnityVector3Convert(this GLTF.Math.Vector3 gltfVec3)
Convert gltf Vector3 to unity Vector3
static Quaternion ToUnityQuaternionRaw(this GLTF.Math.Quaternion quaternion)
static void SetUnityTransform(this Node node, Transform transform)
Set a gltf node&#39;s converted translation, rotation, and scale from a unity transform ...
static Vector4 [] ConvertVector4CoordinateSpaceAndCopy(Vector4[] array, GLTF.Math.Vector4 coordinateSpaceCoordinateScale)
Coverts and copies based on the specified coordinate scale
static GLTF.Math.Vector3 ToGltfVector3Raw(this Vector3 unityVec3)
static Vector4 ToUnityVector4Raw(this GLTF.Math.Vector4 vec4)
static void ConvertVector4CoordinateSpace(ref AttributeAccessor attributeAccessor, GLTF.Math.Vector4 coordinateSpaceCoordinateScale)
Converts vector4 to specified coordinate space
static GLTF.Math.Vector4 ToGltfVector4Raw(this Vector4 unityVec4)
static Vector3 ToUnityVector3Raw(this GLTF.Math.Vector3 vec3)
static void GetUnityTRSProperties(this Node node, out Vector3 position, out Quaternion rotation, out Vector3 scale)
Get the converted unity translation, rotation, and scale from a gltf node
static UnityEngine.Color [] ToUnityColorRaw(this GLTF.Math.Color[] inColorArr)
static GLTF.Math.Matrix4x4 ToGltfMatrix4x4Raw(this Matrix4x4 unityMat)
static UnityEngine.Vector2 [] FlipTexCoordArrayVAndCopy(UnityEngine.Vector2[] array)
Flip the V component of the UV (1-V)
static GLTF.Math.Vector4 GetColumn(this GLTF.Math.Matrix4x4 mat, uint columnNum)
Get a gltf column vector from a gltf matrix
static GLTF.Math.Vector3 ToGltfVector3Convert(this Vector3 unityVec3)
Convert unity Vector3 to gltf Vector3
static int [] FlipFacesAndCopy(int[] triangles)
Rewinds the indices from glTF space to Unity space
static void FlipFaces(ref AttributeAccessor attributeAccessor)
Rewinds the indices into Unity coordinate space from glTF space
static GLTF.Math.Quaternion ToGltfQuaternionRaw(this Quaternion unityQuat)
static GLTF.Math.Matrix4x4 ToGltfMatrix4x4Convert(this Matrix4x4 unityMat)
Convert gltf matrix to a unity matrix
static UnityEngine.Vector3 [] ConvertVector3CoordinateSpaceAndCopy(Vector3[] array, GLTF.Math.Vector3 coordinateSpaceCoordinateScale)
Coverts and copies based on the specified coordinate scale
static Vector3 [] ToUnityVector3Raw(this GLTF.Math.Vector3[] inVecArr)
static Matrix4x4 ToUnityMatrix4x4Raw(this GLTF.Math.Matrix4x4 gltfMat)
static void FlipTexCoordArrayV(ref AttributeAccessor attributeAccessor)
Flips the V component of the UV (1-V) to put from glTF into Unity space
static void GetTRSProperties(this GLTF.Math.Matrix4x4 gltfMat, out Vector3 position, out Quaternion rotation, out Vector3 scale)
Get converted unity translation, rotation, and scale from a gltf matrix