GLTFAccessor.cs 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. using System;
  2. using System.Collections.Generic;
  3. using System.IO;
  4. using System.Threading.Tasks;
  5. using Newtonsoft.Json;
  6. using Siccity.GLTFUtility.Converters;
  7. using UnityEngine;
  8. using UnityEngine.Scripting;
  9. namespace Siccity.GLTFUtility {
  10. // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#accessor
  11. /// <summary> Reads data from BufferViews </summary>
  12. [Preserve] public class GLTFAccessor {
  13. #region Serialized fields
  14. public int? bufferView;
  15. public int byteOffset = 0;
  16. [JsonProperty(Required = Required.Always), JsonConverter(typeof(EnumConverter))] public AccessorType type;
  17. [JsonProperty(Required = Required.Always)] public GLType componentType;
  18. [JsonProperty(Required = Required.Always)] public int count;
  19. public float[] min;
  20. public float[] max;
  21. public Sparse sparse;
  22. #endregion
  23. // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#sparse
  24. [Preserve] public class Sparse {
  25. [JsonProperty(Required = Required.Always)] public int count;
  26. [JsonProperty(Required = Required.Always)] public Indices indices;
  27. [JsonProperty(Required = Required.Always)] public Values values;
  28. // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#values
  29. [Preserve] public class Values {
  30. [JsonProperty(Required = Required.Always)] public int bufferView;
  31. public int byteOffset = 0;
  32. }
  33. // https://github.com/KhronosGroup/glTF/blob/master/specification/2.0/README.md#indices
  34. [Preserve] public class Indices {
  35. [JsonProperty(Required = Required.Always)] public int bufferView;
  36. [JsonProperty(Required = Required.Always)] public GLType componentType;
  37. public int byteOffset = 0;
  38. }
  39. }
  40. #region Import
  41. public class ImportResult {
  42. private const float byteNormalize = 1f / byte.MaxValue;
  43. private const float shortNormalize = 1f / short.MaxValue;
  44. private const float ushortNormalize = 1f / ushort.MaxValue;
  45. private const float intNormalize = 1f / int.MaxValue;
  46. private const float uintNormalize = 1f / uint.MaxValue;
  47. public GLTFBufferView.ImportResult bufferView;
  48. public int? byteStride;
  49. public int count;
  50. public GLType componentType;
  51. public AccessorType type;
  52. public int byteOffset;
  53. public Sparse sparse;
  54. public class Sparse {
  55. public int count;
  56. public Indices indices;
  57. public Values values;
  58. public class Values {
  59. public GLTFBufferView.ImportResult bufferView;
  60. public int byteOffset = 0;
  61. }
  62. public class Indices {
  63. public GLTFBufferView.ImportResult bufferView;
  64. public GLType componentType;
  65. public int byteOffset = 0;
  66. }
  67. }
  68. public Matrix4x4[] ReadMatrix4x4() {
  69. if (!ValidateAccessorType(type, AccessorType.MAT4)) return new Matrix4x4[count];
  70. Func<BufferedBinaryReader, float> floatReader = GetFloatReader(componentType);
  71. Matrix4x4[] m = new Matrix4x4[count];
  72. if (bufferView != null) {
  73. BufferedBinaryReader reader = new BufferedBinaryReader(bufferView.stream, 1024);
  74. reader.Position = bufferView.byteOffset + byteOffset;
  75. int byteSkip = byteStride.HasValue ? byteStride.Value - GetComponentSize() : 0;
  76. for (int i = 0; i < count; i++) {
  77. m[i].m00 = floatReader(reader);
  78. m[i].m01 = floatReader(reader);
  79. m[i].m02 = floatReader(reader);
  80. m[i].m03 = floatReader(reader);
  81. m[i].m10 = floatReader(reader);
  82. m[i].m11 = floatReader(reader);
  83. m[i].m12 = floatReader(reader);
  84. m[i].m13 = floatReader(reader);
  85. m[i].m20 = floatReader(reader);
  86. m[i].m21 = floatReader(reader);
  87. m[i].m22 = floatReader(reader);
  88. m[i].m23 = floatReader(reader);
  89. m[i].m30 = floatReader(reader);
  90. m[i].m31 = floatReader(reader);
  91. m[i].m32 = floatReader(reader);
  92. m[i].m33 = floatReader(reader);
  93. reader.Skip(byteSkip);
  94. }
  95. }
  96. if (sparse != null) {
  97. Func<BufferedBinaryReader, int> indexIntReader = GetIntReader(sparse.indices.componentType);
  98. BufferedBinaryReader indexReader = new BufferedBinaryReader(sparse.indices.bufferView.stream, 1024);
  99. indexReader.Position = sparse.indices.bufferView.byteOffset + sparse.indices.byteOffset;
  100. int[] indices = new int[sparse.count];
  101. for (int i = 0; i < sparse.count; i++) {
  102. indices[i] = indexIntReader(indexReader);
  103. }
  104. BufferedBinaryReader valueReader = new BufferedBinaryReader(sparse.values.bufferView.stream, 1024);
  105. indexReader.Position = sparse.values.bufferView.byteOffset + sparse.values.byteOffset;
  106. for (int i = 0; i < sparse.count; i++) {
  107. int index = indices[i];
  108. m[index].m00 = floatReader(valueReader);
  109. m[index].m01 = floatReader(valueReader);
  110. m[index].m02 = floatReader(valueReader);
  111. m[index].m03 = floatReader(valueReader);
  112. m[index].m10 = floatReader(valueReader);
  113. m[index].m11 = floatReader(valueReader);
  114. m[index].m12 = floatReader(valueReader);
  115. m[index].m13 = floatReader(valueReader);
  116. m[index].m20 = floatReader(valueReader);
  117. m[index].m21 = floatReader(valueReader);
  118. m[index].m22 = floatReader(valueReader);
  119. m[index].m23 = floatReader(valueReader);
  120. m[index].m30 = floatReader(valueReader);
  121. m[index].m31 = floatReader(valueReader);
  122. m[index].m32 = floatReader(valueReader);
  123. m[index].m33 = floatReader(valueReader);
  124. }
  125. }
  126. return m;
  127. }
  128. public Vector4[] ReadVec4(bool normalize = false) {
  129. if (!ValidateAccessorType(type, AccessorType.VEC4)) return new Vector4[count];
  130. Func<BufferedBinaryReader, float> floatReader = normalize ? GetNormalizedFloatReader(componentType) : GetFloatReader(componentType);
  131. Vector4[] v = new Vector4[count];
  132. if (bufferView != null) {
  133. BufferedBinaryReader reader = new BufferedBinaryReader(bufferView.stream, 1024);
  134. reader.Position = bufferView.byteOffset + byteOffset;
  135. int byteSkip = byteStride.HasValue ? byteStride.Value - GetComponentSize() : 0;
  136. for (int i = 0; i < count; i++) {
  137. v[i].x = floatReader(reader);
  138. v[i].y = floatReader(reader);
  139. v[i].z = floatReader(reader);
  140. v[i].w = floatReader(reader);
  141. reader.Skip(byteSkip);
  142. }
  143. }
  144. if (sparse != null) {
  145. Func<BufferedBinaryReader, int> indexIntReader = GetIntReader(sparse.indices.componentType);
  146. BufferedBinaryReader indexReader = new BufferedBinaryReader(sparse.indices.bufferView.stream, 1024);
  147. indexReader.Position = sparse.indices.bufferView.byteOffset + sparse.indices.byteOffset;
  148. int[] indices = new int[sparse.count];
  149. for (int i = 0; i < sparse.count; i++) {
  150. indices[i] = indexIntReader(indexReader);
  151. }
  152. BufferedBinaryReader valueReader = new BufferedBinaryReader(sparse.values.bufferView.stream, 1024);
  153. indexReader.Position = sparse.values.bufferView.byteOffset + sparse.values.byteOffset;
  154. for (int i = 0; i < sparse.count; i++) {
  155. int index = indices[i];
  156. v[index].x = floatReader(valueReader);
  157. v[index].y = floatReader(valueReader);
  158. v[index].z = floatReader(valueReader);
  159. v[index].w = floatReader(valueReader);
  160. }
  161. }
  162. return v;
  163. }
  164. public Color[] ReadColor() {
  165. if (!ValidateAccessorTypeAny(type, AccessorType.VEC3, AccessorType.VEC4)) return new Color[count];
  166. Func<BufferedBinaryReader, float> floatReader = GetNormalizedFloatReader(componentType);
  167. Color[] c = new Color[count];
  168. if (bufferView != null) {
  169. BufferedBinaryReader reader = new BufferedBinaryReader(bufferView.stream, 1024);
  170. reader.Position = bufferView.byteOffset + byteOffset;
  171. int byteSkip = byteStride.HasValue ? byteStride.Value - GetComponentSize() : 0;
  172. if (type == AccessorType.VEC3) {
  173. for (int i = 0; i < count; i++) {
  174. c[i].r = floatReader(reader);
  175. c[i].g = floatReader(reader);
  176. c[i].b = floatReader(reader);
  177. reader.Skip(byteSkip);
  178. }
  179. } else if (type == AccessorType.VEC4) {
  180. for (int i = 0; i < count; i++) {
  181. c[i].r = floatReader(reader);
  182. c[i].g = floatReader(reader);
  183. c[i].b = floatReader(reader);
  184. c[i].a = floatReader(reader);
  185. reader.Skip(byteSkip);
  186. }
  187. }
  188. }
  189. if (sparse != null) {
  190. Func<BufferedBinaryReader, int> indexIntReader = GetIntReader(sparse.indices.componentType);
  191. BufferedBinaryReader indexReader = new BufferedBinaryReader(sparse.indices.bufferView.stream, 1024);
  192. indexReader.Position = sparse.indices.bufferView.byteOffset + sparse.indices.byteOffset;
  193. int[] indices = new int[sparse.count];
  194. for (int i = 0; i < sparse.count; i++) {
  195. indices[i] = indexIntReader(indexReader);
  196. }
  197. BufferedBinaryReader valueReader = new BufferedBinaryReader(sparse.values.bufferView.stream, 1024);
  198. indexReader.Position = sparse.values.bufferView.byteOffset + sparse.values.byteOffset;
  199. if (type == AccessorType.VEC3) {
  200. for (int i = 0; i < sparse.count; i++) {
  201. int index = indices[i];
  202. c[index].r = floatReader(valueReader);
  203. c[index].g = floatReader(valueReader);
  204. c[index].b = floatReader(valueReader);
  205. }
  206. } else if (type == AccessorType.VEC4) {
  207. for (int i = 0; i < sparse.count; i++) {
  208. int index = indices[i];
  209. c[index].r = floatReader(valueReader);
  210. c[index].g = floatReader(valueReader);
  211. c[index].b = floatReader(valueReader);
  212. c[index].a = floatReader(valueReader);
  213. }
  214. }
  215. }
  216. return c;
  217. }
  218. public Vector3[] ReadVec3(bool normalize = false) {
  219. if (!ValidateAccessorType(type, AccessorType.VEC3)) return new Vector3[count];
  220. Func<BufferedBinaryReader, float> floatReader = normalize ? GetNormalizedFloatReader(componentType) : GetFloatReader(componentType);
  221. Vector3[] v = new Vector3[count];
  222. if (bufferView != null) {
  223. BufferedBinaryReader reader = new BufferedBinaryReader(bufferView.stream, 1024);
  224. reader.Position = bufferView.byteOffset + byteOffset;
  225. int byteSkip = byteStride.HasValue ? byteStride.Value - GetComponentSize() : 0;
  226. for (int i = 0; i < count; i++) {
  227. v[i].x = floatReader(reader);
  228. v[i].y = floatReader(reader);
  229. v[i].z = floatReader(reader);
  230. reader.Skip(byteSkip);
  231. }
  232. }
  233. if (sparse != null) {
  234. Func<BufferedBinaryReader, int> indexIntReader = GetIntReader(sparse.indices.componentType);
  235. BufferedBinaryReader indexReader = new BufferedBinaryReader(sparse.indices.bufferView.stream, 1024);
  236. indexReader.Position = sparse.indices.bufferView.byteOffset + sparse.indices.byteOffset;
  237. int[] indices = new int[sparse.count];
  238. for (int i = 0; i < sparse.count; i++) {
  239. indices[i] = indexIntReader(indexReader);
  240. }
  241. BufferedBinaryReader valueReader = new BufferedBinaryReader(sparse.values.bufferView.stream, 1024);
  242. valueReader.Position = sparse.values.bufferView.byteOffset + sparse.values.byteOffset;
  243. for (int i = 0; i < sparse.count; i++) {
  244. int index = indices[i];
  245. v[index].x = floatReader(valueReader);
  246. v[index].y = floatReader(valueReader);
  247. v[index].z = floatReader(valueReader);
  248. }
  249. }
  250. return v;
  251. }
  252. public Vector2[] ReadVec2(bool normalize = false) {
  253. if (!ValidateAccessorType(type, AccessorType.VEC2)) return new Vector2[count];
  254. Func<BufferedBinaryReader, float> floatReader = normalize ? GetNormalizedFloatReader(componentType) : GetFloatReader(componentType);
  255. Vector2[] v = new Vector2[count];
  256. if (bufferView != null) {
  257. BufferedBinaryReader reader = new BufferedBinaryReader(bufferView.stream, 1024);
  258. reader.Position = bufferView.byteOffset + byteOffset;
  259. int byteSkip = byteStride.HasValue ? byteStride.Value - GetComponentSize() : 0;
  260. for (int i = 0; i < count; i++) {
  261. v[i].x = floatReader(reader);
  262. v[i].y = floatReader(reader);
  263. reader.Skip(byteSkip);
  264. }
  265. }
  266. if (sparse != null) {
  267. Func<BufferedBinaryReader, int> indexIntReader = GetIntReader(sparse.indices.componentType);
  268. BufferedBinaryReader indexReader = new BufferedBinaryReader(sparse.indices.bufferView.stream, 1024);
  269. indexReader.Position = sparse.indices.bufferView.byteOffset + sparse.indices.byteOffset;
  270. int[] indices = new int[sparse.count];
  271. for (int i = 0; i < sparse.count; i++) {
  272. indices[i] = indexIntReader(indexReader);
  273. }
  274. BufferedBinaryReader valueReader = new BufferedBinaryReader(sparse.values.bufferView.stream, 1024);
  275. indexReader.Position = sparse.values.bufferView.byteOffset + sparse.values.byteOffset;
  276. for (int i = 0; i < sparse.count; i++) {
  277. int index = indices[i];
  278. v[index].x = floatReader(valueReader);
  279. v[index].y = floatReader(valueReader);
  280. }
  281. }
  282. return v;
  283. }
  284. public float[] ReadFloat() {
  285. if (!ValidateAccessorType(type, AccessorType.SCALAR)) return new float[count];
  286. Func<BufferedBinaryReader, float> floatReader = GetFloatReader(componentType);
  287. float[] f = new float[count];
  288. if (bufferView != null) {
  289. BufferedBinaryReader reader = new BufferedBinaryReader(bufferView.stream, 1024);
  290. reader.Position = bufferView.byteOffset + byteOffset;
  291. int byteSkip = byteStride.HasValue ? byteStride.Value - GetComponentSize() : 0;
  292. for (int i = 0; i < count; i++) {
  293. f[i] = floatReader(reader);
  294. reader.Skip(byteSkip);
  295. }
  296. }
  297. if (sparse != null) {
  298. Func<BufferedBinaryReader, int> indexIntReader = GetIntReader(sparse.indices.componentType);
  299. BufferedBinaryReader indexReader = new BufferedBinaryReader(sparse.indices.bufferView.stream, 1024);
  300. indexReader.Position = sparse.indices.bufferView.byteOffset + sparse.indices.byteOffset;
  301. int[] indices = new int[sparse.count];
  302. for (int i = 0; i < sparse.count; i++) {
  303. indices[i] = indexIntReader(indexReader);
  304. }
  305. BufferedBinaryReader valueReader = new BufferedBinaryReader(sparse.values.bufferView.stream, 1024);
  306. indexReader.Position = sparse.values.bufferView.byteOffset + sparse.values.byteOffset;
  307. for (int i = 0; i < sparse.count; i++) {
  308. int index = indices[i];
  309. f[index] = floatReader(valueReader);
  310. }
  311. }
  312. return f;
  313. }
  314. public int[] ReadInt() {
  315. if (!ValidateAccessorType(type, AccessorType.SCALAR)) return new int[count];
  316. Func<BufferedBinaryReader, int> intReader = GetIntReader(componentType);
  317. int[] v = new int[count];
  318. if (bufferView != null) {
  319. BufferedBinaryReader reader = new BufferedBinaryReader(bufferView.stream, 1024);
  320. reader.Position = bufferView.byteOffset + byteOffset;
  321. int byteSkip = byteStride.HasValue ? byteStride.Value - GetComponentSize() : 0;
  322. for (int i = 0; i < count; i++) {
  323. v[i] = intReader(reader);
  324. reader.Skip(byteSkip);
  325. }
  326. }
  327. if (sparse != null) {
  328. Func<BufferedBinaryReader, int> indexIntReader = GetIntReader(sparse.indices.componentType);
  329. BufferedBinaryReader indexReader = new BufferedBinaryReader(sparse.indices.bufferView.stream, 1024);
  330. indexReader.Position = sparse.indices.bufferView.byteOffset + sparse.indices.byteOffset;
  331. int[] indices = new int[sparse.count];
  332. for (int i = 0; i < sparse.count; i++) {
  333. indices[i] = indexIntReader(indexReader);
  334. }
  335. BufferedBinaryReader valueReader = new BufferedBinaryReader(sparse.values.bufferView.stream, 1024);
  336. indexReader.Position = sparse.values.bufferView.byteOffset + sparse.values.byteOffset;
  337. for (int i = 0; i < sparse.count; i++) {
  338. int index = indices[i];
  339. v[index] = intReader(valueReader);
  340. }
  341. }
  342. return v;
  343. }
  344. public Func<BufferedBinaryReader, int> GetIntReader(GLType componentType) {
  345. Func<BufferedBinaryReader, int> readMethod;
  346. switch (componentType) {
  347. case GLType.BYTE:
  348. return x => x.ReadSByte();
  349. case GLType.UNSIGNED_BYTE:
  350. return readMethod = x => x.ReadByte();
  351. case GLType.FLOAT:
  352. return readMethod = x => (int) x.ReadSingle();
  353. case GLType.SHORT:
  354. return readMethod = x => x.ReadInt16();
  355. case GLType.UNSIGNED_SHORT:
  356. return readMethod = x => x.ReadUInt16();
  357. case GLType.UNSIGNED_INT:
  358. return readMethod = x => (int) x.ReadUInt32();
  359. default:
  360. Debug.LogWarning("No componentType defined");
  361. return readMethod = x => x.ReadInt32();
  362. }
  363. }
  364. public Func<BufferedBinaryReader, float> GetFloatReader(GLType componentType) {
  365. Func<BufferedBinaryReader, float> readMethod;
  366. switch (componentType) {
  367. case GLType.BYTE:
  368. return x => x.ReadSByte();
  369. case GLType.UNSIGNED_BYTE:
  370. return readMethod = x => x.ReadByte();
  371. case GLType.FLOAT:
  372. return readMethod = x => x.ReadSingle();
  373. case GLType.SHORT:
  374. return readMethod = x => x.ReadInt16();
  375. case GLType.UNSIGNED_SHORT:
  376. return readMethod = x => x.ReadUInt16();
  377. case GLType.UNSIGNED_INT:
  378. return readMethod = x => x.ReadUInt32();
  379. default:
  380. Debug.LogWarning("No componentType defined");
  381. return readMethod = x => x.ReadSingle();
  382. }
  383. }
  384. public Func<BufferedBinaryReader, float> GetNormalizedFloatReader(GLType componentType)
  385. {
  386. Func<BufferedBinaryReader, float> readMethod;
  387. switch(componentType)
  388. {
  389. case GLType.BYTE:
  390. return x => x.ReadSByte();
  391. case GLType.UNSIGNED_BYTE:
  392. return readMethod = x => x.ReadByte() * byteNormalize;
  393. case GLType.FLOAT:
  394. return readMethod = x => x.ReadSingle();
  395. case GLType.SHORT:
  396. return readMethod = x => x.ReadInt16() * shortNormalize;
  397. case GLType.UNSIGNED_SHORT:
  398. return readMethod = x => x.ReadUInt16() * ushortNormalize;
  399. case GLType.UNSIGNED_INT:
  400. return readMethod = x => x.ReadUInt32() / uintNormalize;
  401. default:
  402. Debug.LogWarning("No componentType defined");
  403. return readMethod = x => x.ReadSingle();
  404. }
  405. }
  406. /// <summary> Get the size of the attribute type, in bytes </summary>
  407. public int GetComponentSize() {
  408. return type.ComponentCount() * componentType.ByteSize();
  409. }
  410. public static bool ValidateByteStride(int byteStride) {
  411. if (byteStride >= 4 && byteStride <= 252 && byteStride % 4 == 0) return true;
  412. Debug.Log("ByteStride of " + byteStride + " is invalid. Ignoring.");
  413. return false;
  414. }
  415. private static bool ValidateAccessorType(AccessorType type, AccessorType expected) {
  416. if (type == expected) return true;
  417. else {
  418. Debug.LogError("Type mismatch! Expected " + expected + " got " + type);
  419. return false;
  420. }
  421. }
  422. public static bool ValidateAccessorTypeAny(AccessorType type, params AccessorType[] expected) {
  423. for (int i = 0; i < expected.Length; i++) {
  424. if (type == expected[i]) return true;
  425. }
  426. Debug.Log("Type mismatch! Expected " + string.Join("or ", expected) + ", got " + type);
  427. return false;
  428. }
  429. }
  430. public ImportResult Import(GLTFBufferView.ImportResult[] bufferViews) {
  431. ImportResult result = new ImportResult();
  432. result.bufferView = bufferView.HasValue ? bufferViews[bufferView.Value] : null;
  433. result.componentType = componentType;
  434. result.type = type;
  435. result.count = count;
  436. result.byteOffset = byteOffset;
  437. result.byteStride = result.bufferView != null ? result.bufferView.byteStride : null;
  438. // Sparse accessor works by overwriting specified indices instead of defining a full data set. This can save space, especially for morph targets
  439. if (sparse != null) {
  440. result.sparse = new ImportResult.Sparse() {
  441. count = sparse.count,
  442. indices = new ImportResult.Sparse.Indices() {
  443. bufferView = bufferViews[sparse.indices.bufferView],
  444. componentType = sparse.indices.componentType,
  445. byteOffset = sparse.indices.byteOffset
  446. },
  447. values = new ImportResult.Sparse.Values() {
  448. bufferView = bufferViews[sparse.values.bufferView],
  449. byteOffset = sparse.values.byteOffset
  450. }
  451. };
  452. }
  453. return result;
  454. }
  455. public class ImportTask : Importer.ImportTask<ImportResult[]> {
  456. public ImportTask(List<GLTFAccessor> accessors, GLTFBufferView.ImportTask bufferViewTask) : base(bufferViewTask) {
  457. task = new Task(() => {
  458. Result = new ImportResult[accessors.Count];
  459. for (int i = 0; i < Result.Length; i++) {
  460. Result[i] = accessors[i].Import(bufferViewTask.Result);
  461. }
  462. });
  463. }
  464. }
  465. #endregion
  466. }
  467. }