indexcodec.cpp 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752
  1. // This file is part of meshoptimizer library; see meshoptimizer.h for version/license details
  2. #include "meshoptimizer.h"
  3. #include <assert.h>
  4. #include <string.h>
  5. #ifndef TRACE
  6. #define TRACE 0
  7. #endif
  8. #if TRACE
  9. #include <stdio.h>
  10. #endif
  11. // This work is based on:
  12. // Fabian Giesen. Simple lossless index buffer compression & follow-up. 2013
  13. // Conor Stokes. Vertex Cache Optimised Index Buffer Compression. 2014
  14. namespace meshopt
  15. {
  16. const unsigned char kIndexHeader = 0xe0;
  17. const unsigned char kSequenceHeader = 0xd0;
  18. static int gEncodeIndexVersion = 0;
  19. typedef unsigned int VertexFifo[16];
  20. typedef unsigned int EdgeFifo[16][2];
  21. static const unsigned int kTriangleIndexOrder[3][3] = {
  22. {0, 1, 2},
  23. {1, 2, 0},
  24. {2, 0, 1},
  25. };
  26. static const unsigned char kCodeAuxEncodingTable[16] = {
  27. 0x00, 0x76, 0x87, 0x56, 0x67, 0x78, 0xa9, 0x86, 0x65, 0x89, 0x68, 0x98, 0x01, 0x69,
  28. 0, 0, // last two entries aren't used for encoding
  29. };
  30. static int rotateTriangle(unsigned int a, unsigned int b, unsigned int c, unsigned int next)
  31. {
  32. (void)a;
  33. return (b == next) ? 1 : (c == next) ? 2 : 0;
  34. }
  35. static int getEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, unsigned int c, size_t offset)
  36. {
  37. for (int i = 0; i < 16; ++i)
  38. {
  39. size_t index = (offset - 1 - i) & 15;
  40. unsigned int e0 = fifo[index][0];
  41. unsigned int e1 = fifo[index][1];
  42. if (e0 == a && e1 == b)
  43. return (i << 2) | 0;
  44. if (e0 == b && e1 == c)
  45. return (i << 2) | 1;
  46. if (e0 == c && e1 == a)
  47. return (i << 2) | 2;
  48. }
  49. return -1;
  50. }
  51. static void pushEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, size_t& offset)
  52. {
  53. fifo[offset][0] = a;
  54. fifo[offset][1] = b;
  55. offset = (offset + 1) & 15;
  56. }
  57. static int getVertexFifo(VertexFifo fifo, unsigned int v, size_t offset)
  58. {
  59. for (int i = 0; i < 16; ++i)
  60. {
  61. size_t index = (offset - 1 - i) & 15;
  62. if (fifo[index] == v)
  63. return i;
  64. }
  65. return -1;
  66. }
  67. static void pushVertexFifo(VertexFifo fifo, unsigned int v, size_t& offset, int cond = 1)
  68. {
  69. fifo[offset] = v;
  70. offset = (offset + cond) & 15;
  71. }
  72. static void encodeVByte(unsigned char*& data, unsigned int v)
  73. {
  74. // encode 32-bit value in up to 5 7-bit groups
  75. do
  76. {
  77. *data++ = (v & 127) | (v > 127 ? 128 : 0);
  78. v >>= 7;
  79. } while (v);
  80. }
  81. static unsigned int decodeVByte(const unsigned char*& data)
  82. {
  83. unsigned char lead = *data++;
  84. // fast path: single byte
  85. if (lead < 128)
  86. return lead;
  87. // slow path: up to 4 extra bytes
  88. // note that this loop always terminates, which is important for malformed data
  89. unsigned int result = lead & 127;
  90. unsigned int shift = 7;
  91. for (int i = 0; i < 4; ++i)
  92. {
  93. unsigned char group = *data++;
  94. result |= (group & 127) << shift;
  95. shift += 7;
  96. if (group < 128)
  97. break;
  98. }
  99. return result;
  100. }
  101. static void encodeIndex(unsigned char*& data, unsigned int index, unsigned int last)
  102. {
  103. unsigned int d = index - last;
  104. unsigned int v = (d << 1) ^ (int(d) >> 31);
  105. encodeVByte(data, v);
  106. }
  107. static unsigned int decodeIndex(const unsigned char*& data, unsigned int last)
  108. {
  109. unsigned int v = decodeVByte(data);
  110. unsigned int d = (v >> 1) ^ -int(v & 1);
  111. return last + d;
  112. }
  113. static int getCodeAuxIndex(unsigned char v, const unsigned char* table)
  114. {
  115. for (int i = 0; i < 16; ++i)
  116. if (table[i] == v)
  117. return i;
  118. return -1;
  119. }
  120. static void writeTriangle(void* destination, size_t offset, size_t index_size, unsigned int a, unsigned int b, unsigned int c)
  121. {
  122. if (index_size == 2)
  123. {
  124. static_cast<unsigned short*>(destination)[offset + 0] = (unsigned short)(a);
  125. static_cast<unsigned short*>(destination)[offset + 1] = (unsigned short)(b);
  126. static_cast<unsigned short*>(destination)[offset + 2] = (unsigned short)(c);
  127. }
  128. else
  129. {
  130. static_cast<unsigned int*>(destination)[offset + 0] = a;
  131. static_cast<unsigned int*>(destination)[offset + 1] = b;
  132. static_cast<unsigned int*>(destination)[offset + 2] = c;
  133. }
  134. }
  135. #if TRACE
  136. static size_t sortTop16(unsigned char dest[16], size_t stats[256])
  137. {
  138. size_t destsize = 0;
  139. for (size_t i = 0; i < 256; ++i)
  140. {
  141. size_t j = 0;
  142. for (; j < destsize; ++j)
  143. {
  144. if (stats[i] >= stats[dest[j]])
  145. {
  146. if (destsize < 16)
  147. destsize++;
  148. memmove(&dest[j + 1], &dest[j], destsize - 1 - j);
  149. dest[j] = (unsigned char)i;
  150. break;
  151. }
  152. }
  153. if (j == destsize && destsize < 16)
  154. {
  155. dest[destsize] = (unsigned char)i;
  156. destsize++;
  157. }
  158. }
  159. return destsize;
  160. }
  161. #endif
  162. } // namespace meshopt
  163. size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count)
  164. {
  165. using namespace meshopt;
  166. assert(index_count % 3 == 0);
  167. #if TRACE
  168. size_t codestats[256] = {};
  169. size_t codeauxstats[256] = {};
  170. #endif
  171. // the minimum valid encoding is header, 1 byte per triangle and a 16-byte codeaux table
  172. if (buffer_size < 1 + index_count / 3 + 16)
  173. return 0;
  174. int version = gEncodeIndexVersion;
  175. buffer[0] = (unsigned char)(kIndexHeader | version);
  176. EdgeFifo edgefifo;
  177. memset(edgefifo, -1, sizeof(edgefifo));
  178. VertexFifo vertexfifo;
  179. memset(vertexfifo, -1, sizeof(vertexfifo));
  180. size_t edgefifooffset = 0;
  181. size_t vertexfifooffset = 0;
  182. unsigned int next = 0;
  183. unsigned int last = 0;
  184. unsigned char* code = buffer + 1;
  185. unsigned char* data = code + index_count / 3;
  186. unsigned char* data_safe_end = buffer + buffer_size - 16;
  187. int fecmax = version >= 1 ? 13 : 15;
  188. // use static encoding table; it's possible to pack the result and then build an optimal table and repack
  189. // for now we keep it simple and use the table that has been generated based on symbol frequency on a training mesh set
  190. const unsigned char* codeaux_table = kCodeAuxEncodingTable;
  191. for (size_t i = 0; i < index_count; i += 3)
  192. {
  193. // make sure we have enough space to write a triangle
  194. // each triangle writes at most 16 bytes: 1b for codeaux and 5b for each free index
  195. // after this we can be sure we can write without extra bounds checks
  196. if (data > data_safe_end)
  197. return 0;
  198. int fer = getEdgeFifo(edgefifo, indices[i + 0], indices[i + 1], indices[i + 2], edgefifooffset);
  199. if (fer >= 0 && (fer >> 2) < 15)
  200. {
  201. const unsigned int* order = kTriangleIndexOrder[fer & 3];
  202. unsigned int a = indices[i + order[0]], b = indices[i + order[1]], c = indices[i + order[2]];
  203. // encode edge index and vertex fifo index, next or free index
  204. int fe = fer >> 2;
  205. int fc = getVertexFifo(vertexfifo, c, vertexfifooffset);
  206. int fec = (fc >= 1 && fc < fecmax) ? fc : (c == next) ? (next++, 0) : 15;
  207. if (fec == 15 && version >= 1)
  208. {
  209. // encode last-1 and last+1 to optimize strip-like sequences
  210. if (c + 1 == last)
  211. fec = 13, last = c;
  212. if (c == last + 1)
  213. fec = 14, last = c;
  214. }
  215. *code++ = (unsigned char)((fe << 4) | fec);
  216. #if TRACE
  217. codestats[code[-1]]++;
  218. #endif
  219. // note that we need to update the last index since free indices are delta-encoded
  220. if (fec == 15)
  221. encodeIndex(data, c, last), last = c;
  222. // we only need to push third vertex since first two are likely already in the vertex fifo
  223. if (fec == 0 || fec >= fecmax)
  224. pushVertexFifo(vertexfifo, c, vertexfifooffset);
  225. // we only need to push two new edges to edge fifo since the third one is already there
  226. pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  227. pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  228. }
  229. else
  230. {
  231. int rotation = rotateTriangle(indices[i + 0], indices[i + 1], indices[i + 2], next);
  232. const unsigned int* order = kTriangleIndexOrder[rotation];
  233. unsigned int a = indices[i + order[0]], b = indices[i + order[1]], c = indices[i + order[2]];
  234. // if a/b/c are 0/1/2, we emit a reset code
  235. bool reset = false;
  236. if (a == 0 && b == 1 && c == 2 && next > 0 && version >= 1)
  237. {
  238. reset = true;
  239. next = 0;
  240. // reset vertex fifo to make sure we don't accidentally reference vertices from that in the future
  241. // this makes sure next continues to get incremented instead of being stuck
  242. memset(vertexfifo, -1, sizeof(vertexfifo));
  243. }
  244. int fb = getVertexFifo(vertexfifo, b, vertexfifooffset);
  245. int fc = getVertexFifo(vertexfifo, c, vertexfifooffset);
  246. // after rotation, a is almost always equal to next, so we don't waste bits on FIFO encoding for a
  247. int fea = (a == next) ? (next++, 0) : 15;
  248. int feb = (fb >= 0 && fb < 14) ? (fb + 1) : (b == next) ? (next++, 0) : 15;
  249. int fec = (fc >= 0 && fc < 14) ? (fc + 1) : (c == next) ? (next++, 0) : 15;
  250. // we encode feb & fec in 4 bits using a table if possible, and as a full byte otherwise
  251. unsigned char codeaux = (unsigned char)((feb << 4) | fec);
  252. int codeauxindex = getCodeAuxIndex(codeaux, codeaux_table);
  253. // <14 encodes an index into codeaux table, 14 encodes fea=0, 15 encodes fea=15
  254. if (fea == 0 && codeauxindex >= 0 && codeauxindex < 14 && !reset)
  255. {
  256. *code++ = (unsigned char)((15 << 4) | codeauxindex);
  257. }
  258. else
  259. {
  260. *code++ = (unsigned char)((15 << 4) | 14 | fea);
  261. *data++ = codeaux;
  262. }
  263. #if TRACE
  264. codestats[code[-1]]++;
  265. codeauxstats[codeaux]++;
  266. #endif
  267. // note that we need to update the last index since free indices are delta-encoded
  268. if (fea == 15)
  269. encodeIndex(data, a, last), last = a;
  270. if (feb == 15)
  271. encodeIndex(data, b, last), last = b;
  272. if (fec == 15)
  273. encodeIndex(data, c, last), last = c;
  274. // only push vertices that weren't already in fifo
  275. if (fea == 0 || fea == 15)
  276. pushVertexFifo(vertexfifo, a, vertexfifooffset);
  277. if (feb == 0 || feb == 15)
  278. pushVertexFifo(vertexfifo, b, vertexfifooffset);
  279. if (fec == 0 || fec == 15)
  280. pushVertexFifo(vertexfifo, c, vertexfifooffset);
  281. // all three edges aren't in the fifo; pushing all of them is important so that we can match them for later triangles
  282. pushEdgeFifo(edgefifo, b, a, edgefifooffset);
  283. pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  284. pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  285. }
  286. }
  287. // make sure we have enough space to write codeaux table
  288. if (data > data_safe_end)
  289. return 0;
  290. // add codeaux encoding table to the end of the stream; this is used for decoding codeaux *and* as padding
  291. // we need padding for decoding to be able to assume that each triangle is encoded as <= 16 bytes of extra data
  292. // this is enough space for aux byte + 5 bytes per varint index which is the absolute worst case for any input
  293. for (size_t i = 0; i < 16; ++i)
  294. {
  295. // decoder assumes that table entries never refer to separately encoded indices
  296. assert((codeaux_table[i] & 0xf) != 0xf && (codeaux_table[i] >> 4) != 0xf);
  297. *data++ = codeaux_table[i];
  298. }
  299. // since we encode restarts as codeaux without a table reference, we need to make sure 00 is encoded as a table reference
  300. assert(codeaux_table[0] == 0);
  301. assert(data >= buffer + index_count / 3 + 16);
  302. assert(data <= buffer + buffer_size);
  303. #if TRACE
  304. unsigned char codetop[16], codeauxtop[16];
  305. size_t codetopsize = sortTop16(codetop, codestats);
  306. size_t codeauxtopsize = sortTop16(codeauxtop, codeauxstats);
  307. size_t sumcode = 0, sumcodeaux = 0;
  308. for (size_t i = 0; i < 256; ++i)
  309. sumcode += codestats[i], sumcodeaux += codeauxstats[i];
  310. size_t acccode = 0, acccodeaux = 0;
  311. printf("code\t\t\t\t\tcodeaux\n");
  312. for (size_t i = 0; i < codetopsize && i < codeauxtopsize; ++i)
  313. {
  314. acccode += codestats[codetop[i]];
  315. acccodeaux += codeauxstats[codeauxtop[i]];
  316. printf("%2d: %02x = %d (%.1f%% ..%.1f%%)\t\t%2d: %02x = %d (%.1f%% ..%.1f%%)\n",
  317. int(i), codetop[i], int(codestats[codetop[i]]), double(codestats[codetop[i]]) / double(sumcode) * 100, double(acccode) / double(sumcode) * 100,
  318. int(i), codeauxtop[i], int(codeauxstats[codeauxtop[i]]), double(codeauxstats[codeauxtop[i]]) / double(sumcodeaux) * 100, double(acccodeaux) / double(sumcodeaux) * 100);
  319. }
  320. #endif
  321. return data - buffer;
  322. }
  323. size_t meshopt_encodeIndexBufferBound(size_t index_count, size_t vertex_count)
  324. {
  325. assert(index_count % 3 == 0);
  326. // compute number of bits required for each index
  327. unsigned int vertex_bits = 1;
  328. while (vertex_bits < 32 && vertex_count > size_t(1) << vertex_bits)
  329. vertex_bits++;
  330. // worst-case encoding is 2 header bytes + 3 varint-7 encoded index deltas
  331. unsigned int vertex_groups = (vertex_bits + 1 + 6) / 7;
  332. return 1 + (index_count / 3) * (2 + 3 * vertex_groups) + 16;
  333. }
  334. void meshopt_encodeIndexVersion(int version)
  335. {
  336. assert(unsigned(version) <= 1);
  337. meshopt::gEncodeIndexVersion = version;
  338. }
  339. int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size)
  340. {
  341. using namespace meshopt;
  342. assert(index_count % 3 == 0);
  343. assert(index_size == 2 || index_size == 4);
  344. // the minimum valid encoding is header, 1 byte per triangle and a 16-byte codeaux table
  345. if (buffer_size < 1 + index_count / 3 + 16)
  346. return -2;
  347. if ((buffer[0] & 0xf0) != kIndexHeader)
  348. return -1;
  349. int version = buffer[0] & 0x0f;
  350. if (version > 1)
  351. return -1;
  352. EdgeFifo edgefifo;
  353. memset(edgefifo, -1, sizeof(edgefifo));
  354. VertexFifo vertexfifo;
  355. memset(vertexfifo, -1, sizeof(vertexfifo));
  356. size_t edgefifooffset = 0;
  357. size_t vertexfifooffset = 0;
  358. unsigned int next = 0;
  359. unsigned int last = 0;
  360. int fecmax = version >= 1 ? 13 : 15;
  361. // since we store 16-byte codeaux table at the end, triangle data has to begin before data_safe_end
  362. const unsigned char* code = buffer + 1;
  363. const unsigned char* data = code + index_count / 3;
  364. const unsigned char* data_safe_end = buffer + buffer_size - 16;
  365. const unsigned char* codeaux_table = data_safe_end;
  366. for (size_t i = 0; i < index_count; i += 3)
  367. {
  368. // make sure we have enough data to read for a triangle
  369. // each triangle reads at most 16 bytes of data: 1b for codeaux and 5b for each free index
  370. // after this we can be sure we can read without extra bounds checks
  371. if (data > data_safe_end)
  372. return -2;
  373. unsigned char codetri = *code++;
  374. if (codetri < 0xf0)
  375. {
  376. int fe = codetri >> 4;
  377. // fifo reads are wrapped around 16 entry buffer
  378. unsigned int a = edgefifo[(edgefifooffset - 1 - fe) & 15][0];
  379. unsigned int b = edgefifo[(edgefifooffset - 1 - fe) & 15][1];
  380. int fec = codetri & 15;
  381. // note: this is the most common path in the entire decoder
  382. // inside this if we try to stay branchless (by using cmov/etc.) since these aren't predictable
  383. if (fec < fecmax)
  384. {
  385. // fifo reads are wrapped around 16 entry buffer
  386. unsigned int cf = vertexfifo[(vertexfifooffset - 1 - fec) & 15];
  387. unsigned int c = (fec == 0) ? next : cf;
  388. int fec0 = fec == 0;
  389. next += fec0;
  390. // output triangle
  391. writeTriangle(destination, i, index_size, a, b, c);
  392. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  393. pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
  394. pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  395. pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  396. }
  397. else
  398. {
  399. unsigned int c = 0;
  400. // fec - (fec ^ 3) decodes 13, 14 into -1, 1
  401. // note that we need to update the last index since free indices are delta-encoded
  402. last = c = (fec != 15) ? last + (fec - (fec ^ 3)) : decodeIndex(data, last);
  403. // output triangle
  404. writeTriangle(destination, i, index_size, a, b, c);
  405. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  406. pushVertexFifo(vertexfifo, c, vertexfifooffset);
  407. pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  408. pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  409. }
  410. }
  411. else
  412. {
  413. // fast path: read codeaux from the table
  414. if (codetri < 0xfe)
  415. {
  416. unsigned char codeaux = codeaux_table[codetri & 15];
  417. // note: table can't contain feb/fec=15
  418. int feb = codeaux >> 4;
  419. int fec = codeaux & 15;
  420. // fifo reads are wrapped around 16 entry buffer
  421. // also note that we increment next for all three vertices before decoding indices - this matches encoder behavior
  422. unsigned int a = next++;
  423. unsigned int bf = vertexfifo[(vertexfifooffset - feb) & 15];
  424. unsigned int b = (feb == 0) ? next : bf;
  425. int feb0 = feb == 0;
  426. next += feb0;
  427. unsigned int cf = vertexfifo[(vertexfifooffset - fec) & 15];
  428. unsigned int c = (fec == 0) ? next : cf;
  429. int fec0 = fec == 0;
  430. next += fec0;
  431. // output triangle
  432. writeTriangle(destination, i, index_size, a, b, c);
  433. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  434. pushVertexFifo(vertexfifo, a, vertexfifooffset);
  435. pushVertexFifo(vertexfifo, b, vertexfifooffset, feb0);
  436. pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
  437. pushEdgeFifo(edgefifo, b, a, edgefifooffset);
  438. pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  439. pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  440. }
  441. else
  442. {
  443. // slow path: read a full byte for codeaux instead of using a table lookup
  444. unsigned char codeaux = *data++;
  445. int fea = codetri == 0xfe ? 0 : 15;
  446. int feb = codeaux >> 4;
  447. int fec = codeaux & 15;
  448. // reset: codeaux is 0 but encoded as not-a-table
  449. if (codeaux == 0)
  450. next = 0;
  451. // fifo reads are wrapped around 16 entry buffer
  452. // also note that we increment next for all three vertices before decoding indices - this matches encoder behavior
  453. unsigned int a = (fea == 0) ? next++ : 0;
  454. unsigned int b = (feb == 0) ? next++ : vertexfifo[(vertexfifooffset - feb) & 15];
  455. unsigned int c = (fec == 0) ? next++ : vertexfifo[(vertexfifooffset - fec) & 15];
  456. // note that we need to update the last index since free indices are delta-encoded
  457. if (fea == 15)
  458. last = a = decodeIndex(data, last);
  459. if (feb == 15)
  460. last = b = decodeIndex(data, last);
  461. if (fec == 15)
  462. last = c = decodeIndex(data, last);
  463. // output triangle
  464. writeTriangle(destination, i, index_size, a, b, c);
  465. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  466. pushVertexFifo(vertexfifo, a, vertexfifooffset);
  467. pushVertexFifo(vertexfifo, b, vertexfifooffset, (feb == 0) | (feb == 15));
  468. pushVertexFifo(vertexfifo, c, vertexfifooffset, (fec == 0) | (fec == 15));
  469. pushEdgeFifo(edgefifo, b, a, edgefifooffset);
  470. pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  471. pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  472. }
  473. }
  474. }
  475. // we should've read all data bytes and stopped at the boundary between data and codeaux table
  476. if (data != data_safe_end)
  477. return -3;
  478. return 0;
  479. }
  480. size_t meshopt_encodeIndexSequence(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count)
  481. {
  482. using namespace meshopt;
  483. // the minimum valid encoding is header, 1 byte per index and a 4-byte tail
  484. if (buffer_size < 1 + index_count + 4)
  485. return 0;
  486. int version = gEncodeIndexVersion;
  487. buffer[0] = (unsigned char)(kSequenceHeader | version);
  488. unsigned int last[2] = {};
  489. unsigned int current = 0;
  490. unsigned char* data = buffer + 1;
  491. unsigned char* data_safe_end = buffer + buffer_size - 4;
  492. for (size_t i = 0; i < index_count; ++i)
  493. {
  494. // make sure we have enough data to write
  495. // each index writes at most 5 bytes of data; there's a 4 byte tail after data_safe_end
  496. // after this we can be sure we can write without extra bounds checks
  497. if (data >= data_safe_end)
  498. return 0;
  499. unsigned int index = indices[i];
  500. // this is a heuristic that switches between baselines when the delta grows too large
  501. // we want the encoded delta to fit into one byte (7 bits), but 2 bits are used for sign and baseline index
  502. // for now we immediately switch the baseline when delta grows too large - this can be adjusted arbitrarily
  503. int cd = int(index - last[current]);
  504. current ^= ((cd < 0 ? -cd : cd) >= 30);
  505. // encode delta from the last index
  506. unsigned int d = index - last[current];
  507. unsigned int v = (d << 1) ^ (int(d) >> 31);
  508. // note: low bit encodes the index of the last baseline which will be used for reconstruction
  509. encodeVByte(data, (v << 1) | current);
  510. // update last for the next iteration that uses it
  511. last[current] = index;
  512. }
  513. // make sure we have enough space to write tail
  514. if (data > data_safe_end)
  515. return 0;
  516. for (int k = 0; k < 4; ++k)
  517. *data++ = 0;
  518. return data - buffer;
  519. }
  520. size_t meshopt_encodeIndexSequenceBound(size_t index_count, size_t vertex_count)
  521. {
  522. // compute number of bits required for each index
  523. unsigned int vertex_bits = 1;
  524. while (vertex_bits < 32 && vertex_count > size_t(1) << vertex_bits)
  525. vertex_bits++;
  526. // worst-case encoding is 1 varint-7 encoded index delta for a K bit value and an extra bit
  527. unsigned int vertex_groups = (vertex_bits + 1 + 1 + 6) / 7;
  528. return 1 + index_count * vertex_groups + 4;
  529. }
  530. int meshopt_decodeIndexSequence(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size)
  531. {
  532. using namespace meshopt;
  533. // the minimum valid encoding is header, 1 byte per index and a 4-byte tail
  534. if (buffer_size < 1 + index_count + 4)
  535. return -2;
  536. if ((buffer[0] & 0xf0) != kSequenceHeader)
  537. return -1;
  538. int version = buffer[0] & 0x0f;
  539. if (version > 1)
  540. return -1;
  541. const unsigned char* data = buffer + 1;
  542. const unsigned char* data_safe_end = buffer + buffer_size - 4;
  543. unsigned int last[2] = {};
  544. for (size_t i = 0; i < index_count; ++i)
  545. {
  546. // make sure we have enough data to read
  547. // each index reads at most 5 bytes of data; there's a 4 byte tail after data_safe_end
  548. // after this we can be sure we can read without extra bounds checks
  549. if (data >= data_safe_end)
  550. return -2;
  551. unsigned int v = decodeVByte(data);
  552. // decode the index of the last baseline
  553. unsigned int current = v & 1;
  554. v >>= 1;
  555. // reconstruct index as a delta
  556. unsigned int d = (v >> 1) ^ -int(v & 1);
  557. unsigned int index = last[current] + d;
  558. // update last for the next iteration that uses it
  559. last[current] = index;
  560. if (index_size == 2)
  561. {
  562. static_cast<unsigned short*>(destination)[i] = (unsigned short)(index);
  563. }
  564. else
  565. {
  566. static_cast<unsigned int*>(destination)[i] = index;
  567. }
  568. }
  569. // we should've read all data bytes and stopped at the boundary between data and tail
  570. if (data != data_safe_end)
  571. return -3;
  572. return 0;
  573. }