indexcodec.cpp 20 KB

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