Guest User

Untitled

a guest
Jun 20th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 84.98 KB | None | 0 0
  1. diff --git a/src/indexcodec.cpp b/src/indexcodec.cpp
  2. index 4ab92cb..18ccd43 100644
  3. --- a/src/indexcodec.cpp
  4. +++ b/src/indexcodec.cpp
  5. @@ -7,9 +7,6 @@
  6. // This work is based on:
  7. // Fabian Giesen. Simple lossless index buffer compression & follow-up. 2013
  8. // Conor Stokes. Vertex Cache Optimised Index Buffer Compression. 2014
  9. -namespace meshopt
  10. -{
  11. -
  12. const unsigned char kIndexHeader = 0xe0;
  13.  
  14. typedef unsigned int VertexFifo[16];
  15. @@ -53,11 +50,11 @@ static int getEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, unsigned i
  16. return -1;
  17. }
  18.  
  19. -static void pushEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, size_t& offset)
  20. +static void pushEdgeFifo(EdgeFifo fifo, unsigned int a, unsigned int b, size_t* offset)
  21. {
  22. - fifo[offset][0] = a;
  23. - fifo[offset][1] = b;
  24. - offset = (offset + 1) & 15;
  25. + fifo[*offset][0] = a;
  26. + fifo[*offset][1] = b;
  27. + *offset = (*offset + 1) & 15;
  28. }
  29.  
  30. static int getVertexFifo(VertexFifo fifo, unsigned int v, size_t offset)
  31. @@ -73,25 +70,25 @@ static int getVertexFifo(VertexFifo fifo, unsigned int v, size_t offset)
  32. return -1;
  33. }
  34.  
  35. -static void pushVertexFifo(VertexFifo fifo, unsigned int v, size_t& offset, int cond = 1)
  36. +static void pushVertexFifo(VertexFifo fifo, unsigned int v, size_t* offset, int cond)
  37. {
  38. - fifo[offset] = v;
  39. - offset = (offset + cond) & 15;
  40. + fifo[*offset] = v;
  41. + *offset = (*offset + cond) & 15;
  42. }
  43.  
  44. -static void encodeVByte(unsigned char*& data, unsigned int v)
  45. +static void encodeVByte(unsigned char** data, unsigned int v)
  46. {
  47. // encode 32-bit value in up to 5 7-bit groups
  48. do
  49. {
  50. - *data++ = (v & 127) | (v > 127 ? 128 : 0);
  51. + *(*data)++ = (v & 127) | (v > 127 ? 128 : 0);
  52. v >>= 7;
  53. } while (v);
  54. }
  55.  
  56. -static unsigned int decodeVByte(const unsigned char*& data)
  57. +static unsigned int decodeVByte(const unsigned char** data)
  58. {
  59. - unsigned char lead = *data++;
  60. + unsigned char lead = *(*data)++;
  61.  
  62. // fast path: single byte
  63. if (lead < 128)
  64. @@ -104,7 +101,7 @@ static unsigned int decodeVByte(const unsigned char*& data)
  65.  
  66. for (int i = 0; i < 4; ++i)
  67. {
  68. - unsigned char group = *data++;
  69. + unsigned char group = *(*data)++;
  70. result |= (group & 127) << shift;
  71. shift += 7;
  72.  
  73. @@ -115,22 +112,22 @@ static unsigned int decodeVByte(const unsigned char*& data)
  74. return result;
  75. }
  76.  
  77. -static void encodeIndex(unsigned char*& data, unsigned int index, unsigned int next, unsigned int last)
  78. +static void encodeIndex(unsigned char** data, unsigned int index, unsigned int next, unsigned int last)
  79. {
  80. (void)next;
  81.  
  82. unsigned int d = index - last;
  83. - unsigned int v = (d << 1) ^ (int(d) >> 31);
  84. + unsigned int v = (d << 1) ^ ((int)(d) >> 31);
  85.  
  86. encodeVByte(data, v);
  87. }
  88.  
  89. -static unsigned int decodeIndex(const unsigned char*& data, unsigned int next, unsigned int last)
  90. +static unsigned int decodeIndex(const unsigned char** data, unsigned int next, unsigned int last)
  91. {
  92. (void)next;
  93.  
  94. unsigned int v = decodeVByte(data);
  95. - unsigned int d = (v >> 1) ^ -int(v & 1);
  96. + unsigned int d = (v >> 1) ^ -(int)(v & 1);
  97.  
  98. return last + d;
  99. }
  100. @@ -148,24 +145,20 @@ static void writeTriangle(void* destination, size_t offset, size_t index_size, u
  101. {
  102. if (index_size == 2)
  103. {
  104. - static_cast<unsigned short*>(destination)[offset + 0] = static_cast<unsigned short>(a);
  105. - static_cast<unsigned short*>(destination)[offset + 1] = static_cast<unsigned short>(b);
  106. - static_cast<unsigned short*>(destination)[offset + 2] = static_cast<unsigned short>(c);
  107. + ((unsigned short*)destination)[offset + 0] = (unsigned short)(a);
  108. + ((unsigned short*)destination)[offset + 1] = (unsigned short)(b);
  109. + ((unsigned short*)destination)[offset + 2] = (unsigned short)(c);
  110. }
  111. else
  112. {
  113. - static_cast<unsigned int*>(destination)[offset + 0] = a;
  114. - static_cast<unsigned int*>(destination)[offset + 1] = b;
  115. - static_cast<unsigned int*>(destination)[offset + 2] = c;
  116. + ((unsigned int*)destination)[offset + 0] = a;
  117. + ((unsigned int*)destination)[offset + 1] = b;
  118. + ((unsigned int*)destination)[offset + 2] = c;
  119. }
  120. }
  121.  
  122. -} // namespace meshopt
  123. -
  124. size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, const unsigned int* indices, size_t index_count)
  125. {
  126. - using namespace meshopt;
  127. -
  128. assert(index_count % 3 == 0);
  129.  
  130. // the minimum valid encoding is header, 1 byte per triangle and a 16-byte codeaux table
  131. @@ -216,19 +209,19 @@ size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, cons
  132.  
  133. int fec = (fc >= 1 && fc < 15) ? fc : (c == next) ? (next++, 0) : 15;
  134.  
  135. - *code++ = static_cast<unsigned char>((fe << 4) | fec);
  136. + *code++ = (unsigned char)((fe << 4) | fec);
  137.  
  138. // note that we need to update the last index since free indices are delta-encoded
  139. if (fec == 15)
  140. - encodeIndex(data, c, next, last), last = c;
  141. + encodeIndex(&data, c, next, last), last = c;
  142.  
  143. // we only need to push third vertex since first two are likely already in the vertex fifo
  144. if (fec == 0 || fec == 15)
  145. - pushVertexFifo(vertexfifo, c, vertexfifooffset);
  146. + pushVertexFifo(vertexfifo, c, &vertexfifooffset, 1);
  147.  
  148. // we only need to push two new edges to edge fifo since the third one is already there
  149. - pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  150. - pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  151. + pushEdgeFifo(edgefifo, c, b, &edgefifooffset);
  152. + pushEdgeFifo(edgefifo, a, c, &edgefifooffset);
  153. }
  154. else
  155. {
  156. @@ -246,44 +239,44 @@ size_t meshopt_encodeIndexBuffer(unsigned char* buffer, size_t buffer_size, cons
  157. int fec = (fc >= 0 && fc < 14) ? (fc + 1) : (c == next) ? (next++, 0) : 15;
  158.  
  159. // we encode feb & fec in 4 bits using a table if possible, and as a full byte otherwise
  160. - unsigned char codeaux = static_cast<unsigned char>((feb << 4) | fec);
  161. + unsigned char codeaux = (unsigned char)((feb << 4) | fec);
  162. int codeauxindex = getCodeAuxIndex(codeaux, codeaux_table);
  163.  
  164. // <14 encodes an index into codeaux table, 14 encodes fea=0, 15 encodes fea=15
  165. if (fea == 0 && codeauxindex >= 0 && codeauxindex < 14)
  166. {
  167. - *code++ = static_cast<unsigned char>((15 << 4) | codeauxindex);
  168. + *code++ = (unsigned char)((15 << 4) | codeauxindex);
  169. }
  170. else
  171. {
  172. - *code++ = static_cast<unsigned char>((15 << 4) | 14 | fea);
  173. + *code++ = (unsigned char)((15 << 4) | 14 | fea);
  174. *data++ = codeaux;
  175. }
  176.  
  177. // note that we need to update the last index since free indices are delta-encoded
  178. if (fea == 15)
  179. - encodeIndex(data, a, next, last), last = a;
  180. + encodeIndex(&data, a, next, last), last = a;
  181.  
  182. if (feb == 15)
  183. - encodeIndex(data, b, next, last), last = b;
  184. + encodeIndex(&data, b, next, last), last = b;
  185.  
  186. if (fec == 15)
  187. - encodeIndex(data, c, next, last), last = c;
  188. + encodeIndex(&data, c, next, last), last = c;
  189.  
  190. // only push vertices that weren't already in fifo
  191. if (fea == 0 || fea == 15)
  192. - pushVertexFifo(vertexfifo, a, vertexfifooffset);
  193. + pushVertexFifo(vertexfifo, a, &vertexfifooffset, 1);
  194.  
  195. if (feb == 0 || feb == 15)
  196. - pushVertexFifo(vertexfifo, b, vertexfifooffset);
  197. + pushVertexFifo(vertexfifo, b, &vertexfifooffset, 1);
  198.  
  199. if (fec == 0 || fec == 15)
  200. - pushVertexFifo(vertexfifo, c, vertexfifooffset);
  201. + pushVertexFifo(vertexfifo, c, &vertexfifooffset, 1);
  202.  
  203. // all three edges aren't in the fifo; pushing all of them is important so that we can match them for later triangles
  204. - pushEdgeFifo(edgefifo, b, a, edgefifooffset);
  205. - pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  206. - pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  207. + pushEdgeFifo(edgefifo, b, a, &edgefifooffset);
  208. + pushEdgeFifo(edgefifo, c, b, &edgefifooffset);
  209. + pushEdgeFifo(edgefifo, a, c, &edgefifooffset);
  210. }
  211. }
  212.  
  213. @@ -315,7 +308,7 @@ size_t meshopt_encodeIndexBufferBound(size_t index_count, size_t vertex_count)
  214. // compute number of bits required for each index
  215. unsigned int vertex_bits = 1;
  216.  
  217. - while (vertex_bits < 32 && vertex_count > size_t(1) << vertex_bits)
  218. + while (vertex_bits < 32 && vertex_count > (size_t)(1) << vertex_bits)
  219. vertex_bits++;
  220.  
  221. // worst-case encoding is 2 header bytes + 3 varint-7 encoded index deltas
  222. @@ -326,8 +319,6 @@ size_t meshopt_encodeIndexBufferBound(size_t index_count, size_t vertex_count)
  223.  
  224. int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t index_size, const unsigned char* buffer, size_t buffer_size)
  225. {
  226. - using namespace meshopt;
  227. -
  228. assert(index_count % 3 == 0);
  229. assert(index_size == 2 || index_size == 4);
  230.  
  231. @@ -392,26 +383,26 @@ int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t inde
  232. writeTriangle(destination, i, index_size, a, b, c);
  233.  
  234. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  235. - pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
  236. + pushVertexFifo(vertexfifo, c, &vertexfifooffset, fec0);
  237.  
  238. - pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  239. - pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  240. + pushEdgeFifo(edgefifo, c, b, &edgefifooffset);
  241. + pushEdgeFifo(edgefifo, a, c, &edgefifooffset);
  242. }
  243. else
  244. {
  245. unsigned int c = 0;
  246.  
  247. // note that we need to update the last index since free indices are delta-encoded
  248. - last = c = decodeIndex(data, next, last);
  249. + last = c = decodeIndex(&data, next, last);
  250.  
  251. // output triangle
  252. writeTriangle(destination, i, index_size, a, b, c);
  253.  
  254. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  255. - pushVertexFifo(vertexfifo, c, vertexfifooffset);
  256. + pushVertexFifo(vertexfifo, c, &vertexfifooffset, 1);
  257.  
  258. - pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  259. - pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  260. + pushEdgeFifo(edgefifo, c, b, &edgefifooffset);
  261. + pushEdgeFifo(edgefifo, a, c, &edgefifooffset);
  262. }
  263. }
  264. else
  265. @@ -445,13 +436,13 @@ int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t inde
  266. writeTriangle(destination, i, index_size, a, b, c);
  267.  
  268. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  269. - pushVertexFifo(vertexfifo, a, vertexfifooffset);
  270. - pushVertexFifo(vertexfifo, b, vertexfifooffset, feb0);
  271. - pushVertexFifo(vertexfifo, c, vertexfifooffset, fec0);
  272. + pushVertexFifo(vertexfifo, a, &vertexfifooffset, 1);
  273. + pushVertexFifo(vertexfifo, b, &vertexfifooffset, feb0);
  274. + pushVertexFifo(vertexfifo, c, &vertexfifooffset, fec0);
  275.  
  276. - pushEdgeFifo(edgefifo, b, a, edgefifooffset);
  277. - pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  278. - pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  279. + pushEdgeFifo(edgefifo, b, a, &edgefifooffset);
  280. + pushEdgeFifo(edgefifo, c, b, &edgefifooffset);
  281. + pushEdgeFifo(edgefifo, a, c, &edgefifooffset);
  282. }
  283. else
  284. {
  285. @@ -470,25 +461,25 @@ int meshopt_decodeIndexBuffer(void* destination, size_t index_count, size_t inde
  286.  
  287. // note that we need to update the last index since free indices are delta-encoded
  288. if (fea == 15)
  289. - last = a = decodeIndex(data, next, last);
  290. + last = a = decodeIndex(&data, next, last);
  291.  
  292. if (feb == 15)
  293. - last = b = decodeIndex(data, next, last);
  294. + last = b = decodeIndex(&data, next, last);
  295.  
  296. if (fec == 15)
  297. - last = c = decodeIndex(data, next, last);
  298. + last = c = decodeIndex(&data, next, last);
  299.  
  300. // output triangle
  301. writeTriangle(destination, i, index_size, a, b, c);
  302.  
  303. // push vertex/edge fifo must match the encoding step *exactly* otherwise the data will not be decoded correctly
  304. - pushVertexFifo(vertexfifo, a, vertexfifooffset);
  305. - pushVertexFifo(vertexfifo, b, vertexfifooffset, (feb == 0) | (feb == 15));
  306. - pushVertexFifo(vertexfifo, c, vertexfifooffset, (fec == 0) | (fec == 15));
  307. + pushVertexFifo(vertexfifo, a, &vertexfifooffset, 1);
  308. + pushVertexFifo(vertexfifo, b, &vertexfifooffset, (feb == 0) | (feb == 15));
  309. + pushVertexFifo(vertexfifo, c, &vertexfifooffset, (fec == 0) | (fec == 15));
  310.  
  311. - pushEdgeFifo(edgefifo, b, a, edgefifooffset);
  312. - pushEdgeFifo(edgefifo, c, b, edgefifooffset);
  313. - pushEdgeFifo(edgefifo, a, c, edgefifooffset);
  314. + pushEdgeFifo(edgefifo, b, a, &edgefifooffset);
  315. + pushEdgeFifo(edgefifo, c, b, &edgefifooffset);
  316. + pushEdgeFifo(edgefifo, a, c, &edgefifooffset);
  317. }
  318. }
  319. }
  320. diff --git a/src/indexgenerator.cpp b/src/indexgenerator.cpp
  321. index 066b15e..c5eb706 100644
  322. --- a/src/indexgenerator.cpp
  323. +++ b/src/indexgenerator.cpp
  324. @@ -2,49 +2,48 @@
  325. #include "meshoptimizer.h"
  326.  
  327. #include <assert.h>
  328. +#include <stdbool.h>
  329. +#include <stdlib.h>
  330. #include <string.h>
  331.  
  332. -namespace meshopt
  333. -{
  334. -
  335. -struct VertexHasher
  336. +typedef struct VertexHasher
  337. {
  338. const char* vertices;
  339. size_t vertex_size;
  340. +} VertexHasher;
  341.  
  342. - size_t hash(unsigned int index) const
  343. - {
  344. - // MurmurHash2
  345. - const unsigned int m = 0x5bd1e995;
  346. - const int r = 24;
  347. +static size_t hash(const VertexHasher* hasher, unsigned int index)
  348. +{
  349. + // MurmurHash2
  350. + const unsigned int m = 0x5bd1e995;
  351. + const int r = 24;
  352.  
  353. - unsigned int h = 0;
  354. - const char* key = vertices + index * vertex_size;
  355. - size_t len = vertex_size;
  356. + unsigned int h = 0;
  357. + const char* key = hasher->vertices + index * hasher->vertex_size;
  358. + size_t len = hasher->vertex_size;
  359.  
  360. - while (len >= 4)
  361. - {
  362. - unsigned int k = *reinterpret_cast<const unsigned int*>(key);
  363. -
  364. - k *= m;
  365. - k ^= k >> r;
  366. - k *= m;
  367. + while (len >= 4)
  368. + {
  369. + unsigned int k = *(const unsigned int*)(key);
  370.  
  371. - h *= m;
  372. - h ^= k;
  373. + k *= m;
  374. + k ^= k >> r;
  375. + k *= m;
  376.  
  377. - key += 4;
  378. - len -= 4;
  379. - }
  380. + h *= m;
  381. + h ^= k;
  382.  
  383. - return h;
  384. + key += 4;
  385. + len -= 4;
  386. }
  387.  
  388. - bool equal(unsigned int lhs, unsigned int rhs) const
  389. - {
  390. - return memcmp(vertices + lhs * vertex_size, vertices + rhs * vertex_size, vertex_size) == 0;
  391. - }
  392. -};
  393. + return h;
  394. +}
  395. +
  396. +static bool equal(const VertexHasher* hasher, unsigned int lhs, unsigned int rhs)
  397. +{
  398. + return memcmp(hasher->vertices + lhs * hasher->vertex_size, hasher->vertices + rhs * hasher->vertex_size, hasher->vertex_size) == 0;
  399. +}
  400.  
  401. static size_t hashBuckets(size_t count)
  402. {
  403. @@ -55,24 +54,23 @@ static size_t hashBuckets(size_t count)
  404. return buckets;
  405. }
  406.  
  407. -template <typename T, typename Hash>
  408. -static T* hashLookup(T* table, size_t buckets, const Hash& hash, const T& key, const T& empty)
  409. +static unsigned int* hashLookup(unsigned int* table, size_t buckets, const VertexHasher* hasher, unsigned int key, unsigned int empty)
  410. {
  411. assert(buckets > 0);
  412. assert((buckets & (buckets - 1)) == 0);
  413.  
  414. size_t hashmod = buckets - 1;
  415. - size_t bucket = hash.hash(key) & hashmod;
  416. + size_t bucket = hash(hasher, key) & hashmod;
  417.  
  418. for (size_t probe = 0; probe <= hashmod; ++probe)
  419. {
  420. - T& item = table[bucket];
  421. + unsigned int* item = &table[bucket];
  422.  
  423. - if (item == empty)
  424. - return &item;
  425. + if (*item == empty)
  426. + return item;
  427.  
  428. - if (hash.equal(item, key))
  429. - return &item;
  430. + if (equal(hasher, *item, key))
  431. + return item;
  432.  
  433. // hash collision, quadratic probing
  434. bucket = (bucket + probe + 1) & hashmod;
  435. @@ -82,33 +80,30 @@ static T* hashLookup(T* table, size_t buckets, const Hash& hash, const T& key, c
  436. return 0;
  437. }
  438.  
  439. -} // namespace meshopt
  440. -
  441. size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int* indices, size_t index_count, const void* vertices, size_t vertex_count, size_t vertex_size)
  442. {
  443. - using namespace meshopt;
  444. -
  445. assert(indices || index_count == vertex_count);
  446. assert(index_count % 3 == 0);
  447. assert(vertex_size > 0 && vertex_size <= 256);
  448.  
  449. memset(destination, -1, vertex_count * sizeof(unsigned int));
  450.  
  451. - VertexHasher hasher = {static_cast<const char*>(vertices), vertex_size};
  452. + VertexHasher hasher = {(const char*)(vertices), vertex_size};
  453.  
  454. - meshopt_Buffer<unsigned int> table(hashBuckets(vertex_count));
  455. - memset(table.data, -1, table.size * sizeof(unsigned int));
  456. + size_t buckets = hashBuckets(vertex_count);
  457. + unsigned int* table = malloc(buckets * sizeof(unsigned int));
  458. + memset(table, -1, buckets * sizeof(unsigned int));
  459.  
  460. unsigned int next_vertex = 0;
  461.  
  462. for (size_t i = 0; i < index_count; ++i)
  463. {
  464. - unsigned int index = indices ? indices[i] : unsigned(i);
  465. + unsigned int index = indices ? indices[i] : (unsigned)(i);
  466. assert(index < vertex_count);
  467.  
  468. if (destination[index] == ~0u)
  469. {
  470. - unsigned int* entry = hashLookup(table.data, table.size, hasher, index, ~0u);
  471. + unsigned int* entry = hashLookup(table, buckets, &hasher, index, ~0u);
  472.  
  473. if (*entry == ~0u)
  474. {
  475. @@ -125,6 +120,8 @@ size_t meshopt_generateVertexRemap(unsigned int* destination, const unsigned int
  476. }
  477. }
  478.  
  479. + free(table);
  480. +
  481. assert(next_vertex <= vertex_count);
  482.  
  483. return next_vertex;
  484. @@ -135,13 +132,13 @@ void meshopt_remapVertexBuffer(void* destination, const void* vertices, size_t v
  485. assert(vertex_size > 0 && vertex_size <= 256);
  486.  
  487. // support in-place remap
  488. - meshopt_Buffer<char> vertices_copy;
  489. + char* vertices_copy = 0;
  490.  
  491. if (destination == vertices)
  492. {
  493. - vertices_copy.allocate(vertex_count * vertex_size);
  494. - memcpy(vertices_copy.data, vertices, vertex_count * vertex_size);
  495. - vertices = vertices_copy.data;
  496. + vertices_copy = malloc(vertex_count * vertex_size);
  497. + memcpy(vertices_copy, vertices, vertex_count * vertex_size);
  498. + vertices = vertices_copy;
  499. }
  500.  
  501. for (size_t i = 0; i < vertex_count; ++i)
  502. @@ -150,9 +147,11 @@ void meshopt_remapVertexBuffer(void* destination, const void* vertices, size_t v
  503. {
  504. assert(remap[i] < vertex_count);
  505.  
  506. - memcpy(static_cast<char*>(destination) + remap[i] * vertex_size, static_cast<const char*>(vertices) + i * vertex_size, vertex_size);
  507. + memcpy((char*)(destination) + remap[i] * vertex_size, (const char*)(vertices) + i * vertex_size, vertex_size);
  508. }
  509. }
  510. +
  511. + free(vertices_copy);
  512. }
  513.  
  514. void meshopt_remapIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const unsigned int* remap)
  515. @@ -161,7 +160,7 @@ void meshopt_remapIndexBuffer(unsigned int* destination, const unsigned int* ind
  516.  
  517. for (size_t i = 0; i < index_count; ++i)
  518. {
  519. - unsigned int index = indices ? indices[i] : unsigned(i);
  520. + unsigned int index = indices ? indices[i] : (unsigned)(i);
  521. assert(remap[index] != ~0u);
  522.  
  523. destination[i] = remap[index];
  524. diff --git a/src/meshoptimizer.h b/src/meshoptimizer.h
  525. index a9850bd..6219397 100644
  526. --- a/src/meshoptimizer.h
  527. +++ b/src/meshoptimizer.h
  528. @@ -212,7 +212,7 @@ MESHOPTIMIZER_API struct meshopt_VertexFetchStatistics meshopt_analyzeVertexFetc
  529. #endif
  530.  
  531. /* Quantization into commonly supported data formats */
  532. -#ifdef __cplusplus
  533. +#if 1 // todo: c99?
  534. /**
  535. * Quantize a float in [0..1] range into an N-bit fixed point unorm value
  536. * Assumes reconstruction function (q / (2^N-1)), which is the case for fixed-function normalized fixed point conversion
  537. @@ -429,27 +429,27 @@ inline meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const T* indices
  538. #endif
  539.  
  540. /* Inline implementation */
  541. -#ifdef __cplusplus
  542. +#if 1 // todo: C99?
  543. inline int meshopt_quantizeUnorm(float v, int N)
  544. {
  545. - const float scale = float((1 << N) - 1);
  546. + const float scale = (float)((1 << N) - 1);
  547.  
  548. v = (v >= 0) ? v : 0;
  549. v = (v <= 1) ? v : 1;
  550.  
  551. - return int(v * scale + 0.5f);
  552. + return (int)(v * scale + 0.5f);
  553. }
  554.  
  555. inline int meshopt_quantizeSnorm(float v, int N)
  556. {
  557. - const float scale = float((1 << (N - 1)) - 1);
  558. + const float scale = (float)((1 << (N - 1)) - 1);
  559.  
  560. float round = (v >= 0 ? 0.5f : -0.5f);
  561.  
  562. v = (v >= -1) ? v : -1;
  563. v = (v <= +1) ? v : +1;
  564.  
  565. - return int(v * scale + round);
  566. + return (int)(v * scale + round);
  567. }
  568.  
  569. inline unsigned short meshopt_quantizeHalf(float v)
  570. diff --git a/src/overdrawanalyzer.cpp b/src/overdrawanalyzer.cpp
  571. index aad88b9..0cbde43 100644
  572. --- a/src/overdrawanalyzer.cpp
  573. +++ b/src/overdrawanalyzer.cpp
  574. @@ -7,25 +7,30 @@
  575.  
  576. // This work is based on:
  577. // Nicolas Capens. Advanced Rasterization. 2004
  578. -namespace meshopt
  579. -{
  580. -
  581. -const int kViewport = 256;
  582. +enum { kViewport = 256 };
  583.  
  584. -struct OverdrawBuffer
  585. +typedef struct OverdrawBuffer
  586. {
  587. float z[kViewport][kViewport][2];
  588. unsigned int overdraw[kViewport][kViewport][2];
  589. -};
  590. +} OverdrawBuffer;
  591.  
  592. -template <typename T>
  593. -static T min(T a, T b)
  594. +static float minf(float a, float b)
  595. {
  596. return a < b ? a : b;
  597. }
  598.  
  599. -template <typename T>
  600. -static T max(T a, T b)
  601. +static int mini(int a, int b)
  602. +{
  603. + return a < b ? a : b;
  604. +}
  605. +
  606. +static float maxf(float a, float b)
  607. +{
  608. + return a > b ? a : b;
  609. +}
  610. +
  611. +static int maxi(int a, int b)
  612. {
  613. return a > b ? a : b;
  614. }
  615. @@ -37,7 +42,7 @@ static float det2x2(float a, float b, float c, float d)
  616. return a * d - b * c;
  617. }
  618.  
  619. -static float computeDepthGradients(float& dzdx, float& dzdy, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3)
  620. +static float computeDepthGradients(float* dzdx, float* dzdy, float x1, float y1, float z1, float x2, float y2, float z2, float x3, float y3, float z3)
  621. {
  622. // z2 = z1 + dzdx * (x2 - x1) + dzdy * (y2 - y1)
  623. // z3 = z1 + dzdx * (x3 - x1) + dzdy * (y3 - y1)
  624. @@ -47,8 +52,8 @@ static float computeDepthGradients(float& dzdx, float& dzdy, float x1, float y1,
  625. float det = det2x2(x2 - x1, y2 - y1, x3 - x1, y3 - y1);
  626. float invdet = (det == 0) ? 0 : 1 / det;
  627.  
  628. - dzdx = det2x2(z2 - z1, y2 - y1, z3 - z1, y3 - y1) * invdet;
  629. - dzdy = det2x2(x2 - x1, z2 - z1, x3 - x1, z3 - z1) * invdet;
  630. + *dzdx = det2x2(z2 - z1, y2 - y1, z3 - z1, y3 - y1) * invdet;
  631. + *dzdy = det2x2(x2 - x1, z2 - z1, x3 - x1, z3 - z1) * invdet;
  632.  
  633. return det;
  634. }
  635. @@ -58,7 +63,7 @@ static void rasterize(OverdrawBuffer* buffer, float v1x, float v1y, float v1z, f
  636. {
  637. // compute depth gradients
  638. float DZx, DZy;
  639. - float det = computeDepthGradients(DZx, DZy, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z);
  640. + float det = computeDepthGradients(&DZx, &DZy, v1x, v1y, v1z, v2x, v2y, v2z, v3x, v3y, v3z);
  641. int sign = det > 0;
  642.  
  643. // flip backfacing triangles to simplify rasterization logic
  644. @@ -77,22 +82,22 @@ static void rasterize(OverdrawBuffer* buffer, float v1x, float v1y, float v1z, f
  645. }
  646.  
  647. // coordinates, 28.4 fixed point
  648. - int X1 = int(16.0f * v1x + 0.5f);
  649. - int X2 = int(16.0f * v2x + 0.5f);
  650. - int X3 = int(16.0f * v3x + 0.5f);
  651. + int X1 = (int)(16.0f * v1x + 0.5f);
  652. + int X2 = (int)(16.0f * v2x + 0.5f);
  653. + int X3 = (int)(16.0f * v3x + 0.5f);
  654.  
  655. - int Y1 = int(16.0f * v1y + 0.5f);
  656. - int Y2 = int(16.0f * v2y + 0.5f);
  657. - int Y3 = int(16.0f * v3y + 0.5f);
  658. + int Y1 = (int)(16.0f * v1y + 0.5f);
  659. + int Y2 = (int)(16.0f * v2y + 0.5f);
  660. + int Y3 = (int)(16.0f * v3y + 0.5f);
  661.  
  662. // bounding rectangle, clipped against viewport
  663. // since we rasterize pixels with covered centers, min >0.5 should round up
  664. // as for max, due to top-left filling convention we will never rasterize right/bottom edges
  665. // so max >= 0.5 should round down
  666. - int minx = max((min(X1, min(X2, X3)) + 7) >> 4, 0);
  667. - int maxx = min((max(X1, max(X2, X3)) + 7) >> 4, kViewport);
  668. - int miny = max((min(Y1, min(Y2, Y3)) + 7) >> 4, 0);
  669. - int maxy = min((max(Y1, max(Y2, Y3)) + 7) >> 4, kViewport);
  670. + int minx = maxi((mini(X1, mini(X2, X3)) + 7) >> 4, 0);
  671. + int maxx = mini((maxi(X1, maxi(X2, X3)) + 7) >> 4, kViewport);
  672. + int miny = maxi((mini(Y1, mini(Y2, Y3)) + 7) >> 4, 0);
  673. + int maxy = mini((maxi(Y1, maxi(Y2, Y3)) + 7) >> 4, kViewport);
  674.  
  675. // deltas, 28.4 fixed point
  676. int DX12 = X1 - X2;
  677. @@ -115,7 +120,7 @@ static void rasterize(OverdrawBuffer* buffer, float v1x, float v1y, float v1z, f
  678. int CY1 = DX12 * (FY - Y1) - DY12 * (FX - X1) + TL1 - 1;
  679. int CY2 = DX23 * (FY - Y2) - DY23 * (FX - X2) + TL2 - 1;
  680. int CY3 = DX31 * (FY - Y3) - DY31 * (FX - X3) + TL3 - 1;
  681. - float ZY = v1z + (DZx * float(FX - X1) + DZy * float(FY - Y1)) * (1 / 16.f);
  682. + float ZY = v1z + (DZx * (float)(FX - X1) + DZy * (float)(FY - Y1)) * (1 / 16.f);
  683.  
  684. for (int y = miny; y < maxy; y++)
  685. {
  686. @@ -149,19 +154,15 @@ static void rasterize(OverdrawBuffer* buffer, float v1x, float v1y, float v1z, f
  687. }
  688. }
  689.  
  690. -} // namespace meshopt
  691. -
  692. -meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride)
  693. +struct meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride)
  694. {
  695. - using namespace meshopt;
  696. -
  697. assert(index_count % 3 == 0);
  698. assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
  699. assert(vertex_positions_stride % sizeof(float) == 0);
  700.  
  701. size_t vertex_stride_float = vertex_positions_stride / sizeof(float);
  702.  
  703. - meshopt_OverdrawStatistics result = {};
  704. + struct meshopt_OverdrawStatistics result = {};
  705.  
  706. float minv[3] = {FLT_MAX, FLT_MAX, FLT_MAX};
  707. float maxv[3] = {-FLT_MAX, -FLT_MAX, -FLT_MAX};
  708. @@ -172,15 +173,15 @@ meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices,
  709.  
  710. for (int j = 0; j < 3; ++j)
  711. {
  712. - minv[j] = min(minv[j], v[j]);
  713. - maxv[j] = max(maxv[j], v[j]);
  714. + minv[j] = minf(minv[j], v[j]);
  715. + maxv[j] = maxf(maxv[j], v[j]);
  716. }
  717. }
  718.  
  719. - float extent = max(maxv[0] - minv[0], max(maxv[1] - minv[1], maxv[2] - minv[2]));
  720. + float extent = maxf(maxv[0] - minv[0], maxf(maxv[1] - minv[1], maxv[2] - minv[2]));
  721. float scale = kViewport / extent;
  722.  
  723. - meshopt_Buffer<float> triangles(index_count * 3);
  724. + float* triangles = malloc(index_count * 3 * sizeof(float));
  725.  
  726. for (size_t i = 0; i < index_count; ++i)
  727. {
  728. @@ -194,8 +195,7 @@ meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices,
  729. triangles[i * 3 + 2] = (v[2] - minv[2]) * scale;
  730. }
  731.  
  732. - meshopt_Buffer<OverdrawBuffer> buffer_storage(1);
  733. - OverdrawBuffer* buffer = buffer_storage.data;
  734. + OverdrawBuffer* buffer = malloc(sizeof(OverdrawBuffer));
  735.  
  736. for (int axis = 0; axis < 3; ++axis)
  737. {
  738. @@ -232,7 +232,10 @@ meshopt_OverdrawStatistics meshopt_analyzeOverdraw(const unsigned int* indices,
  739. }
  740. }
  741.  
  742. - result.overdraw = result.pixels_covered ? float(result.pixels_shaded) / float(result.pixels_covered) : 0.f;
  743. + free(buffer);
  744. + free(triangles);
  745. +
  746. + result.overdraw = result.pixels_covered ? (float)(result.pixels_shaded) / (float)(result.pixels_covered) : 0.f;
  747.  
  748. return result;
  749. }
  750. diff --git a/src/overdrawoptimizer.cpp b/src/overdrawoptimizer.cpp
  751. index c3d7724..216001e 100644
  752. --- a/src/overdrawoptimizer.cpp
  753. +++ b/src/overdrawoptimizer.cpp
  754. @@ -7,8 +7,6 @@
  755.  
  756. // This work is based on:
  757. // Pedro Sander, Diego Nehab and Joshua Barczak. Fast Triangle Reordering for Vertex Locality and Reduced Overdraw. 2007
  758. -namespace meshopt
  759. -{
  760.  
  761. static void calculateSortData(float* sort_data, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_positions_stride, const unsigned int* clusters, size_t cluster_count)
  762. {
  763. @@ -119,7 +117,7 @@ static void calculateSortOrderRadix(unsigned int* sort_order, const float* sort_
  764. for (size_t i = 0; i < 1 << sort_bits; ++i)
  765. {
  766. size_t count = histogram[i];
  767. - histogram[i] = unsigned(histogram_sum);
  768. + histogram[i] = (unsigned)(histogram_sum);
  769. histogram_sum += count;
  770. }
  771.  
  772. @@ -128,30 +126,30 @@ static void calculateSortOrderRadix(unsigned int* sort_order, const float* sort_
  773. // compute sort order based on offsets
  774. for (size_t i = 0; i < cluster_count; ++i)
  775. {
  776. - sort_order[histogram[sort_keys[i]]++] = unsigned(i);
  777. + sort_order[histogram[sort_keys[i]]++] = (unsigned)(i);
  778. }
  779. }
  780.  
  781. -static unsigned int updateCache(unsigned int a, unsigned int b, unsigned int c, unsigned int cache_size, unsigned int* cache_timestamps, unsigned int& timestamp)
  782. +static unsigned int updateCache(unsigned int a, unsigned int b, unsigned int c, unsigned int cache_size, unsigned int* cache_timestamps, unsigned int* timestamp)
  783. {
  784. unsigned int cache_misses = 0;
  785.  
  786. // if vertex is not in cache, put it in cache
  787. - if (timestamp - cache_timestamps[a] > cache_size)
  788. + if (*timestamp - cache_timestamps[a] > cache_size)
  789. {
  790. - cache_timestamps[a] = timestamp++;
  791. + cache_timestamps[a] = *timestamp++;
  792. cache_misses++;
  793. }
  794.  
  795. - if (timestamp - cache_timestamps[b] > cache_size)
  796. + if (*timestamp - cache_timestamps[b] > cache_size)
  797. {
  798. - cache_timestamps[b] = timestamp++;
  799. + cache_timestamps[b] = *timestamp++;
  800. cache_misses++;
  801. }
  802.  
  803. - if (timestamp - cache_timestamps[c] > cache_size)
  804. + if (*timestamp - cache_timestamps[c] > cache_size)
  805. {
  806. - cache_timestamps[c] = timestamp++;
  807. + cache_timestamps[c] = *timestamp++;
  808. cache_misses++;
  809. }
  810.  
  811. @@ -160,8 +158,8 @@ static unsigned int updateCache(unsigned int a, unsigned int b, unsigned int c,
  812.  
  813. static size_t generateHardBoundaries(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
  814. {
  815. - meshopt_Buffer<unsigned int> cache_timestamps(vertex_count);
  816. - memset(cache_timestamps.data, 0, vertex_count * sizeof(unsigned int));
  817. + unsigned int* cache_timestamps = malloc(vertex_count * sizeof(unsigned int));
  818. + memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
  819.  
  820. unsigned int timestamp = cache_size + 1;
  821.  
  822. @@ -171,7 +169,7 @@ static size_t generateHardBoundaries(unsigned int* destination, const unsigned i
  823.  
  824. for (size_t i = 0; i < face_count; ++i)
  825. {
  826. - unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], timestamp);
  827. + unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], &timestamp);
  828.  
  829. // when all three vertices are not in the cache it's usually relatively safe to assume that this is a new patch in the mesh
  830. // that is disjoint from previous vertices; sometimes it might come back to reference existing vertices but that frequently
  831. @@ -179,10 +177,12 @@ static size_t generateHardBoundaries(unsigned int* destination, const unsigned i
  832. // usually the first triangle has 3 misses unless it's degenerate - thus we make sure the first cluster always starts with 0
  833. if (i == 0 || m == 3)
  834. {
  835. - destination[result++] = unsigned(i);
  836. + destination[result++] = (unsigned)(i);
  837. }
  838. }
  839.  
  840. + free(cache_timestamps);
  841. +
  842. assert(result <= index_count / 3);
  843.  
  844. return result;
  845. @@ -190,8 +190,8 @@ static size_t generateHardBoundaries(unsigned int* destination, const unsigned i
  846.  
  847. static size_t generateSoftBoundaries(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, const unsigned int* clusters, size_t cluster_count, unsigned int cache_size, float threshold)
  848. {
  849. - meshopt_Buffer<unsigned int> cache_timestamps(vertex_count);
  850. - memset(cache_timestamps.data, 0, vertex_count * sizeof(unsigned int));
  851. + unsigned int* cache_timestamps = malloc(vertex_count * sizeof(unsigned int));
  852. + memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
  853.  
  854. unsigned int timestamp = 0;
  855.  
  856. @@ -211,15 +211,15 @@ static size_t generateSoftBoundaries(unsigned int* destination, const unsigned i
  857.  
  858. for (size_t i = start; i < end; ++i)
  859. {
  860. - unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], timestamp);
  861. + unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], &timestamp);
  862.  
  863. cluster_misses += m;
  864. }
  865.  
  866. - float cluster_threshold = threshold * (float(cluster_misses) / float(end - start));
  867. + float cluster_threshold = threshold * ((float)(cluster_misses) / (float)(end - start));
  868.  
  869. // first cluster always starts from the hard cluster boundary
  870. - destination[result++] = unsigned(start);
  871. + destination[result++] = (unsigned)(start);
  872.  
  873. // reset cache
  874. timestamp += cache_size + 1;
  875. @@ -229,17 +229,17 @@ static size_t generateSoftBoundaries(unsigned int* destination, const unsigned i
  876.  
  877. for (size_t i = start; i < end; ++i)
  878. {
  879. - unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], timestamp);
  880. + unsigned int m = updateCache(indices[i * 3 + 0], indices[i * 3 + 1], indices[i * 3 + 2], cache_size, &cache_timestamps[0], &timestamp);
  881.  
  882. running_misses += m;
  883. running_faces += 1;
  884.  
  885. - if (float(running_misses) / float(running_faces) <= cluster_threshold)
  886. + if ((float)(running_misses) / (float)(running_faces) <= cluster_threshold)
  887. {
  888. // we have reached the target ACMR with the current triangle so we need to start a new cluster on the next one
  889. // note that this may mean that we add 'end` to destination for the last triangle, which will imply that the last
  890. // cluster is empty; however, the 'pop_back' after the loop will clean it up
  891. - destination[result++] = unsigned(i + 1);
  892. + destination[result++] = (unsigned)(i + 1);
  893.  
  894. // reset cache
  895. timestamp += cache_size + 1;
  896. @@ -261,18 +261,16 @@ static size_t generateSoftBoundaries(unsigned int* destination, const unsigned i
  897. }
  898. }
  899.  
  900. + free(cache_timestamps);
  901. +
  902. assert(result >= cluster_count);
  903. assert(result <= index_count / 3);
  904.  
  905. return result;
  906. }
  907.  
  908. -} // namespace meshopt
  909. -
  910. void meshopt_optimizeOverdraw(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride, float threshold)
  911. {
  912. - using namespace meshopt;
  913. -
  914. assert(index_count % 3 == 0);
  915. assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
  916. assert(vertex_positions_stride % sizeof(float) == 0);
  917. @@ -282,35 +280,35 @@ void meshopt_optimizeOverdraw(unsigned int* destination, const unsigned int* ind
  918. return;
  919.  
  920. // support in-place optimization
  921. - meshopt_Buffer<unsigned int> indices_copy;
  922. + unsigned int* indices_copy = 0;
  923.  
  924. if (destination == indices)
  925. {
  926. - indices_copy.allocate(index_count);
  927. - memcpy(indices_copy.data, indices, index_count * sizeof(unsigned int));
  928. - indices = indices_copy.data;
  929. + indices_copy = malloc(index_count * sizeof(unsigned int));
  930. + memcpy(indices_copy, indices, index_count * sizeof(unsigned int));
  931. + indices = indices_copy;
  932. }
  933.  
  934. unsigned int cache_size = 16;
  935.  
  936. // generate hard boundaries from full-triangle cache misses
  937. - meshopt_Buffer<unsigned int> hard_clusters(index_count / 3);
  938. + unsigned int* hard_clusters = malloc((index_count / 3) * sizeof(unsigned int));
  939. size_t hard_cluster_count = generateHardBoundaries(&hard_clusters[0], indices, index_count, vertex_count, cache_size);
  940.  
  941. // generate soft boundaries
  942. - meshopt_Buffer<unsigned int> soft_clusters(index_count / 3 + 1);
  943. + unsigned int* soft_clusters = malloc((index_count / 3 + 1) * sizeof(unsigned int));
  944. size_t soft_cluster_count = generateSoftBoundaries(&soft_clusters[0], indices, index_count, vertex_count, &hard_clusters[0], hard_cluster_count, cache_size, threshold);
  945.  
  946. const unsigned int* clusters = &soft_clusters[0];
  947. size_t cluster_count = soft_cluster_count;
  948.  
  949. // fill sort data
  950. - meshopt_Buffer<float> sort_data(cluster_count);
  951. + float* sort_data = malloc(cluster_count * sizeof(float));
  952. calculateSortData(&sort_data[0], indices, index_count, vertex_positions, vertex_positions_stride, clusters, cluster_count);
  953.  
  954. // sort clusters using sort data
  955. - meshopt_Buffer<unsigned short> sort_keys(cluster_count);
  956. - meshopt_Buffer<unsigned int> sort_order(cluster_count);
  957. + unsigned short* sort_keys = malloc(cluster_count * sizeof(unsigned short));
  958. + unsigned int* sort_order = malloc(cluster_count * sizeof(unsigned int));
  959. calculateSortOrderRadix(&sort_order[0], &sort_data[0], &sort_keys[0], cluster_count);
  960.  
  961. // fill output buffer
  962. @@ -330,4 +328,11 @@ void meshopt_optimizeOverdraw(unsigned int* destination, const unsigned int* ind
  963. }
  964.  
  965. assert(offset == index_count);
  966. +
  967. + free(sort_order);
  968. + free(sort_keys);
  969. + free(sort_data);
  970. + free(soft_clusters);
  971. + free(hard_clusters);
  972. + free(indices_copy);
  973. }
  974. diff --git a/src/simplifier.cpp b/src/simplifier.cpp
  975. index cfc4880..2ba40f4 100644
  976. --- a/src/simplifier.cpp
  977. +++ b/src/simplifier.cpp
  978. @@ -13,35 +13,26 @@
  979.  
  980. // This work is based on:
  981. // Michael Garland and Paul S. Heckbert. Surface simplification using quadric error metrics. 1997
  982. -namespace meshopt
  983. -{
  984.  
  985. -struct EdgeAdjacency
  986. +typedef struct EdgeAdjacency
  987. {
  988. - meshopt_Buffer<unsigned int> counts;
  989. - meshopt_Buffer<unsigned int> offsets;
  990. - meshopt_Buffer<unsigned int> data;
  991. -
  992. - EdgeAdjacency(size_t index_count, size_t vertex_count)
  993. - : counts(vertex_count)
  994. - , offsets(vertex_count)
  995. - , data(index_count)
  996. - {
  997. - }
  998. -};
  999. + unsigned int* counts;
  1000. + unsigned int* offsets;
  1001. + unsigned int* data;
  1002. +} EdgeAdjacency;
  1003.  
  1004. -static void buildEdgeAdjacency(EdgeAdjacency& adjacency, const unsigned int* indices, size_t index_count, size_t vertex_count)
  1005. +static void buildEdgeAdjacency(EdgeAdjacency* adjacency, const unsigned int* indices, size_t index_count, size_t vertex_count)
  1006. {
  1007. size_t face_count = index_count / 3;
  1008.  
  1009. // fill edge counts
  1010. - memset(adjacency.counts.data, 0, vertex_count * sizeof(unsigned int));
  1011. + memset(adjacency->counts, 0, vertex_count * sizeof(unsigned int));
  1012.  
  1013. for (size_t i = 0; i < index_count; ++i)
  1014. {
  1015. assert(indices[i] < vertex_count);
  1016.  
  1017. - adjacency.counts[indices[i]]++;
  1018. + adjacency->counts[indices[i]]++;
  1019. }
  1020.  
  1021. // fill offset table
  1022. @@ -49,8 +40,8 @@ static void buildEdgeAdjacency(EdgeAdjacency& adjacency, const unsigned int* ind
  1023.  
  1024. for (size_t i = 0; i < vertex_count; ++i)
  1025. {
  1026. - adjacency.offsets[i] = offset;
  1027. - offset += adjacency.counts[i];
  1028. + adjacency->offsets[i] = offset;
  1029. + offset += adjacency->counts[i];
  1030. }
  1031.  
  1032. assert(offset == index_count);
  1033. @@ -60,24 +51,24 @@ static void buildEdgeAdjacency(EdgeAdjacency& adjacency, const unsigned int* ind
  1034. {
  1035. unsigned int a = indices[i * 3 + 0], b = indices[i * 3 + 1], c = indices[i * 3 + 2];
  1036.  
  1037. - adjacency.data[adjacency.offsets[a]++] = b;
  1038. - adjacency.data[adjacency.offsets[b]++] = c;
  1039. - adjacency.data[adjacency.offsets[c]++] = a;
  1040. + adjacency->data[adjacency->offsets[a]++] = b;
  1041. + adjacency->data[adjacency->offsets[b]++] = c;
  1042. + adjacency->data[adjacency->offsets[c]++] = a;
  1043. }
  1044.  
  1045. // fix offsets that have been disturbed by the previous pass
  1046. for (size_t i = 0; i < vertex_count; ++i)
  1047. {
  1048. - assert(adjacency.offsets[i] >= adjacency.counts[i]);
  1049. + assert(adjacency->offsets[i] >= adjacency->counts[i]);
  1050.  
  1051. - adjacency.offsets[i] -= adjacency.counts[i];
  1052. + adjacency->offsets[i] -= adjacency->counts[i];
  1053. }
  1054. }
  1055.  
  1056. -static bool findEdge(const EdgeAdjacency& adjacency, unsigned int a, unsigned int b)
  1057. +static bool findEdge(const EdgeAdjacency* adjacency, unsigned int a, unsigned int b)
  1058. {
  1059. - unsigned int count = adjacency.counts[a];
  1060. - const unsigned int* data = adjacency.data.data + adjacency.offsets[a];
  1061. + unsigned int count = adjacency->counts[a];
  1062. + const unsigned int* data = adjacency->data + adjacency->offsets[a];
  1063.  
  1064. for (size_t i = 0; i < count; ++i)
  1065. if (data[i] == b)
  1066. @@ -86,40 +77,40 @@ static bool findEdge(const EdgeAdjacency& adjacency, unsigned int a, unsigned in
  1067. return false;
  1068. }
  1069.  
  1070. -struct PositionHasher
  1071. +typedef struct PositionHasher
  1072. {
  1073. const float* vertex_positions;
  1074. size_t vertex_stride_float;
  1075. +} PositionHasher;
  1076.  
  1077. - size_t hash(unsigned int index) const
  1078. - {
  1079. - // MurmurHash2
  1080. - const unsigned int m = 0x5bd1e995;
  1081. - const int r = 24;
  1082. +static size_t hash2(const PositionHasher* hasher, unsigned int index)
  1083. +{
  1084. + // MurmurHash2
  1085. + const unsigned int m = 0x5bd1e995;
  1086. + const int r = 24;
  1087.  
  1088. - unsigned int h = 0;
  1089. - const unsigned int* key = reinterpret_cast<const unsigned int*>(vertex_positions + index * vertex_stride_float);
  1090. + unsigned int h = 0;
  1091. + const unsigned int* key = (const unsigned int*)(hasher->vertex_positions + index * hasher->vertex_stride_float);
  1092.  
  1093. - for (size_t i = 0; i < 3; ++i)
  1094. - {
  1095. - unsigned int k = key[i];
  1096. -
  1097. - k *= m;
  1098. - k ^= k >> r;
  1099. - k *= m;
  1100. + for (size_t i = 0; i < 3; ++i)
  1101. + {
  1102. + unsigned int k = key[i];
  1103.  
  1104. - h *= m;
  1105. - h ^= k;
  1106. - }
  1107. + k *= m;
  1108. + k ^= k >> r;
  1109. + k *= m;
  1110.  
  1111. - return h;
  1112. + h *= m;
  1113. + h ^= k;
  1114. }
  1115.  
  1116. - bool equal(unsigned int lhs, unsigned int rhs) const
  1117. - {
  1118. - return memcmp(vertex_positions + lhs * vertex_stride_float, vertex_positions + rhs * vertex_stride_float, 12) == 0;
  1119. - }
  1120. -};
  1121. + return h;
  1122. +}
  1123. +
  1124. +static bool equal2(const PositionHasher* hasher, unsigned int lhs, unsigned int rhs)
  1125. +{
  1126. + return memcmp(hasher->vertex_positions + lhs * hasher->vertex_stride_float, hasher->vertex_positions + rhs * hasher->vertex_stride_float, 12) == 0;
  1127. +}
  1128.  
  1129. // TODO: is there a better way to resolve naming conflicts with indexgenerator.cpp?
  1130. static size_t hashBuckets2(size_t count)
  1131. @@ -132,24 +123,23 @@ static size_t hashBuckets2(size_t count)
  1132. }
  1133.  
  1134. // TODO: is there a better way to resolve naming conflicts with indexgenerator.cpp?
  1135. -template <typename T, typename Hash>
  1136. -static T* hashLookup2(T* table, size_t buckets, const Hash& hash, const T& key, const T& empty)
  1137. +static unsigned int* hashLookup2(unsigned int* table, size_t buckets, const PositionHasher* hasher, unsigned int key, unsigned int empty)
  1138. {
  1139. assert(buckets > 0);
  1140. assert((buckets & (buckets - 1)) == 0);
  1141.  
  1142. size_t hashmod = buckets - 1;
  1143. - size_t bucket = hash.hash(key) & hashmod;
  1144. + size_t bucket = hash2(hasher, key) & hashmod;
  1145.  
  1146. for (size_t probe = 0; probe <= hashmod; ++probe)
  1147. {
  1148. - T& item = table[bucket];
  1149. + unsigned int* item = &table[bucket];
  1150.  
  1151. - if (item == empty)
  1152. - return &item;
  1153. + if (*item == empty)
  1154. + return item;
  1155.  
  1156. - if (hash.equal(item, key))
  1157. - return &item;
  1158. + if (equal2(hasher, *item, key))
  1159. + return item;
  1160.  
  1161. // hash collision, quadratic probing
  1162. bucket = (bucket + probe + 1) & hashmod;
  1163. @@ -163,15 +153,16 @@ static void buildPositionRemap(unsigned int* remap, unsigned int* reverse_remap,
  1164. {
  1165. PositionHasher hasher = {vertex_positions_data, vertex_positions_stride / sizeof(float)};
  1166.  
  1167. - meshopt_Buffer<unsigned int> table(hashBuckets2(vertex_count));
  1168. - memset(table.data, -1, table.size * sizeof(unsigned int));
  1169. + size_t buckets = hashBuckets2(vertex_count);
  1170. + unsigned int* table = malloc(buckets * sizeof(unsigned int));
  1171. + memset(table, -1, buckets * sizeof(unsigned int));
  1172.  
  1173. // build forward remap: for each vertex, which other (canonical) vertex does it map to?
  1174. // we use position equivalence for this, and remap vertices to other existing vertices
  1175. for (size_t i = 0; i < vertex_count; ++i)
  1176. {
  1177. - unsigned int index = unsigned(i);
  1178. - unsigned int* entry = hashLookup2(table.data, table.size, hasher, index, ~0u);
  1179. + unsigned int index = (unsigned)(i);
  1180. + unsigned int* entry = hashLookup2(table, buckets, &hasher, index, ~0u);
  1181.  
  1182. if (*entry == ~0u)
  1183. {
  1184. @@ -190,18 +181,20 @@ static void buildPositionRemap(unsigned int* remap, unsigned int* reverse_remap,
  1185. // build reverse remap table: for each vertex, which other vertex remaps to this one?
  1186. // this is a many-to-one relationship, but we only identify vertices for which it's 2-1 (so a pair of vertices)
  1187. for (size_t i = 0; i < vertex_count; ++i)
  1188. - reverse_remap[i] = unsigned(i);
  1189. + reverse_remap[i] = (unsigned)(i);
  1190.  
  1191. for (size_t i = 0; i < vertex_count; ++i)
  1192. if (remap[i] != i)
  1193. {
  1194. // first vertex to remap to remap[i]: keep
  1195. if (reverse_remap[remap[i]] == remap[i])
  1196. - reverse_remap[remap[i]] = unsigned(i);
  1197. + reverse_remap[remap[i]] = (unsigned)(i);
  1198. // more than one vertex, invalidate entry
  1199. else
  1200. reverse_remap[remap[i]] = ~0u;
  1201. }
  1202. +
  1203. + free(table);
  1204. }
  1205.  
  1206. enum VertexKind
  1207. @@ -224,12 +217,12 @@ const char kCanCollapse[Kind_Count][Kind_Count] = {
  1208. {0, 0, 0, 0},
  1209. };
  1210.  
  1211. -static size_t countOpenEdges(const EdgeAdjacency& adjacency, unsigned int vertex, unsigned int* last = 0)
  1212. +static size_t countOpenEdges(const EdgeAdjacency* adjacency, unsigned int vertex, unsigned int* last)
  1213. {
  1214. size_t result = 0;
  1215.  
  1216. - unsigned int count = adjacency.counts[vertex];
  1217. - const unsigned int* data = adjacency.data.data + adjacency.offsets[vertex];
  1218. + unsigned int count = adjacency->counts[vertex];
  1219. + const unsigned int* data = adjacency->data + adjacency->offsets[vertex];
  1220.  
  1221. for (size_t i = 0; i < count; ++i)
  1222. if (!findEdge(adjacency, data[i], vertex))
  1223. @@ -243,7 +236,7 @@ static size_t countOpenEdges(const EdgeAdjacency& adjacency, unsigned int vertex
  1224. return result;
  1225. }
  1226.  
  1227. -static void classifyVertices(unsigned char* result, size_t vertex_count, const EdgeAdjacency& adjacency, const unsigned int* remap, const unsigned int* reverse_remap, size_t lockedstats[4])
  1228. +static void classifyVertices(unsigned char* result, size_t vertex_count, const EdgeAdjacency* adjacency, const unsigned int* remap, const unsigned int* reverse_remap, size_t lockedstats[4])
  1229. {
  1230. for (size_t i = 0; i < vertex_count; ++i)
  1231. {
  1232. @@ -252,7 +245,8 @@ static void classifyVertices(unsigned char* result, size_t vertex_count, const E
  1233. if (reverse_remap[i] == i)
  1234. {
  1235. // no attribute seam, need to check if it's manifold
  1236. - size_t edges = countOpenEdges(adjacency, unsigned(i));
  1237. + unsigned int dummy;
  1238. + size_t edges = countOpenEdges(adjacency, (unsigned)(i), &dummy);
  1239.  
  1240. // note: we classify any vertices with no open edges as manifold
  1241. // this is technically incorrect - if 4 triangles share an edge, we'll classify vertices as manifold
  1242. @@ -270,7 +264,7 @@ static void classifyVertices(unsigned char* result, size_t vertex_count, const E
  1243. {
  1244. // attribute seam; need to distinguish between Seam and Locked
  1245. unsigned int a = 0;
  1246. - size_t a_count = countOpenEdges(adjacency, unsigned(i), &a);
  1247. + size_t a_count = countOpenEdges(adjacency, (unsigned)(i), &a);
  1248. unsigned int b = 0;
  1249. size_t b_count = countOpenEdges(adjacency, reverse_remap[i], &b);
  1250.  
  1251. @@ -282,7 +276,7 @@ static void classifyVertices(unsigned char* result, size_t vertex_count, const E
  1252. unsigned int bf = (remap[b] == b) ? reverse_remap[b] : remap[b];
  1253.  
  1254. if (af != ~0u && findEdge(adjacency, af, reverse_remap[i]) &&
  1255. - bf != ~0u && findEdge(adjacency, bf, unsigned(i)))
  1256. + bf != ~0u && findEdge(adjacency, bf, (unsigned)(i)))
  1257. result[i] = Kind_Seam;
  1258. else
  1259. result[i] = Kind_Locked, lockedstats[1]++;
  1260. @@ -307,20 +301,20 @@ static void classifyVertices(unsigned char* result, size_t vertex_count, const E
  1261. }
  1262. }
  1263.  
  1264. -struct Vector3
  1265. +typedef struct Vector3
  1266. {
  1267. float x, y, z;
  1268. -};
  1269. +} Vector3;
  1270.  
  1271. -struct Quadric
  1272. +typedef struct Quadric
  1273. {
  1274. float a00;
  1275. float a10, a11;
  1276. float a20, a21, a22;
  1277. float b0, b1, b2, c;
  1278. -};
  1279. +} Quadric;
  1280.  
  1281. -struct Collapse
  1282. +typedef struct Collapse
  1283. {
  1284. unsigned int v0;
  1285. unsigned int v1;
  1286. @@ -329,87 +323,87 @@ struct Collapse
  1287. float error;
  1288. unsigned int errorui;
  1289. };
  1290. -};
  1291. +} Collapse;
  1292.  
  1293. -static float normalize(Vector3& v)
  1294. +static float normalize(Vector3* v)
  1295. {
  1296. - float length = sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
  1297. + float length = sqrtf(v->x * v->x + v->y * v->y + v->z * v->z);
  1298.  
  1299. if (length > 0)
  1300. {
  1301. - v.x /= length;
  1302. - v.y /= length;
  1303. - v.z /= length;
  1304. + v->x /= length;
  1305. + v->y /= length;
  1306. + v->z /= length;
  1307. }
  1308.  
  1309. return length;
  1310. }
  1311.  
  1312. -static void quadricAdd(Quadric& Q, const Quadric& R)
  1313. +static void quadricAdd(Quadric* Q, const Quadric* R)
  1314. {
  1315. - Q.a00 += R.a00;
  1316. - Q.a10 += R.a10;
  1317. - Q.a11 += R.a11;
  1318. - Q.a20 += R.a20;
  1319. - Q.a21 += R.a21;
  1320. - Q.a22 += R.a22;
  1321. - Q.b0 += R.b0;
  1322. - Q.b1 += R.b1;
  1323. - Q.b2 += R.b2;
  1324. - Q.c += R.c;
  1325. + Q->a00 += R->a00;
  1326. + Q->a10 += R->a10;
  1327. + Q->a11 += R->a11;
  1328. + Q->a20 += R->a20;
  1329. + Q->a21 += R->a21;
  1330. + Q->a22 += R->a22;
  1331. + Q->b0 += R->b0;
  1332. + Q->b1 += R->b1;
  1333. + Q->b2 += R->b2;
  1334. + Q->c += R->c;
  1335. }
  1336.  
  1337. -static void quadricMul(Quadric& Q, float s)
  1338. +static void quadricMul(Quadric* Q, float s)
  1339. {
  1340. - Q.a00 *= s;
  1341. - Q.a10 *= s;
  1342. - Q.a11 *= s;
  1343. - Q.a20 *= s;
  1344. - Q.a21 *= s;
  1345. - Q.a22 *= s;
  1346. - Q.b0 *= s;
  1347. - Q.b1 *= s;
  1348. - Q.b2 *= s;
  1349. - Q.c *= s;
  1350. + Q->a00 *= s;
  1351. + Q->a10 *= s;
  1352. + Q->a11 *= s;
  1353. + Q->a20 *= s;
  1354. + Q->a21 *= s;
  1355. + Q->a22 *= s;
  1356. + Q->b0 *= s;
  1357. + Q->b1 *= s;
  1358. + Q->b2 *= s;
  1359. + Q->c *= s;
  1360. }
  1361.  
  1362. -static float quadricError(Quadric& Q, const Vector3& v)
  1363. +static float quadricError(Quadric* Q, const Vector3* v)
  1364. {
  1365. - float xx = v.x * v.x;
  1366. - float xy = v.x * v.y;
  1367. - float xz = v.x * v.z;
  1368. - float yy = v.y * v.y;
  1369. - float yz = v.y * v.z;
  1370. - float zz = v.z * v.z;
  1371. + float xx = v->x * v->x;
  1372. + float xy = v->x * v->y;
  1373. + float xz = v->x * v->z;
  1374. + float yy = v->y * v->y;
  1375. + float yz = v->y * v->z;
  1376. + float zz = v->z * v->z;
  1377.  
  1378. - float vTQv = Q.a00 * xx + Q.a10 * xy * 2 + Q.a11 * yy + Q.a20 * xz * 2 + Q.a21 * yz * 2 + Q.a22 * zz + Q.b0 * v.x * 2 + Q.b1 * v.y * 2 + Q.b2 * v.z * 2 + Q.c;
  1379. + float vTQv = Q->a00 * xx + Q->a10 * xy * 2 + Q->a11 * yy + Q->a20 * xz * 2 + Q->a21 * yz * 2 + Q->a22 * zz + Q->b0 * v->x * 2 + Q->b1 * v->y * 2 + Q->b2 * v->z * 2 + Q->c;
  1380.  
  1381. return fabsf(vTQv);
  1382. }
  1383.  
  1384. -static void quadricFromPlane(Quadric& Q, float a, float b, float c, float d)
  1385. +static void quadricFromPlane(Quadric* Q, float a, float b, float c, float d)
  1386. {
  1387. - Q.a00 = a * a;
  1388. - Q.a10 = b * a;
  1389. - Q.a11 = b * b;
  1390. - Q.a20 = c * a;
  1391. - Q.a21 = c * b;
  1392. - Q.a22 = c * c;
  1393. - Q.b0 = d * a;
  1394. - Q.b1 = d * b;
  1395. - Q.b2 = d * c;
  1396. - Q.c = d * d;
  1397. + Q->a00 = a * a;
  1398. + Q->a10 = b * a;
  1399. + Q->a11 = b * b;
  1400. + Q->a20 = c * a;
  1401. + Q->a21 = c * b;
  1402. + Q->a22 = c * c;
  1403. + Q->b0 = d * a;
  1404. + Q->b1 = d * b;
  1405. + Q->b2 = d * c;
  1406. + Q->c = d * d;
  1407. }
  1408.  
  1409. -static void quadricFromTriangle(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2)
  1410. +static void quadricFromTriangle(Quadric* Q, const Vector3* p0, const Vector3* p1, const Vector3* p2)
  1411. {
  1412. - Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
  1413. - Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
  1414. + Vector3 p10 = {p1->x - p0->x, p1->y - p0->y, p1->z - p0->z};
  1415. + Vector3 p20 = {p2->x - p0->x, p2->y - p0->y, p2->z - p0->z};
  1416.  
  1417. Vector3 normal = {p10.y * p20.z - p10.z * p20.y, p10.z * p20.x - p10.x * p20.z, p10.x * p20.y - p10.y * p20.x};
  1418. - float area = normalize(normal);
  1419. + float area = normalize(&normal);
  1420.  
  1421. - float distance = normal.x * p0.x + normal.y * p0.y + normal.z * p0.z;
  1422. + float distance = normal.x * p0->x + normal.y * p0->y + normal.z * p0->z;
  1423.  
  1424. quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance);
  1425.  
  1426. @@ -419,18 +413,18 @@ static void quadricFromTriangle(Quadric& Q, const Vector3& p0, const Vector3& p1
  1427. quadricMul(Q, area);
  1428. }
  1429.  
  1430. -static void quadricFromTriangleEdge(Quadric& Q, const Vector3& p0, const Vector3& p1, const Vector3& p2, float weight)
  1431. +static void quadricFromTriangleEdge(Quadric* Q, const Vector3* p0, const Vector3* p1, const Vector3* p2, float weight)
  1432. {
  1433. - Vector3 p10 = {p1.x - p0.x, p1.y - p0.y, p1.z - p0.z};
  1434. - float length = normalize(p10);
  1435. + Vector3 p10 = {p1->x - p0->x, p1->y - p0->y, p1->z - p0->z};
  1436. + float length = normalize(&p10);
  1437.  
  1438. - Vector3 p20 = {p2.x - p0.x, p2.y - p0.y, p2.z - p0.z};
  1439. + Vector3 p20 = {p2->x - p0->x, p2->y - p0->y, p2->z - p0->z};
  1440. float p20p = p20.x * p10.x + p20.y * p10.y + p20.z * p10.z;
  1441.  
  1442. Vector3 normal = {p20.x - p10.x * p20p, p20.y - p10.y * p20p, p20.z - p10.z * p20p};
  1443. - normalize(normal);
  1444. + normalize(&normal);
  1445.  
  1446. - float distance = normal.x * p0.x + normal.y * p0.y + normal.z * p0.z;
  1447. + float distance = normal.x * p0->x + normal.y * p0->y + normal.z * p0->z;
  1448.  
  1449. // TODO: We should be able to encode squared distance to the edge here?
  1450. quadricFromPlane(Q, normal.x, normal.y, normal.z, -distance);
  1451. @@ -459,7 +453,7 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse
  1452. for (size_t i = 0; i < 1 << sort_bits; ++i)
  1453. {
  1454. size_t count = histogram[i];
  1455. - histogram[i] = unsigned(histogram_sum);
  1456. + histogram[i] = (unsigned)(histogram_sum);
  1457. histogram_sum += count;
  1458. }
  1459.  
  1460. @@ -470,19 +464,15 @@ static void sortEdgeCollapses(unsigned int* sort_order, const Collapse* collapse
  1461. {
  1462. unsigned int key = (collapses[i].errorui << 1) >> (32 - sort_bits);
  1463.  
  1464. - sort_order[histogram[key]++] = unsigned(i);
  1465. + sort_order[histogram[key]++] = (unsigned)(i);
  1466. }
  1467. }
  1468.  
  1469. -} // namespace meshopt
  1470. -
  1471. // TODO: this is necessary for lodviewer but will go away at some point
  1472. unsigned char* meshopt_simplifyDebugKind = 0;
  1473.  
  1474. size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions_data, size_t vertex_count, size_t vertex_positions_stride, size_t target_index_count)
  1475. {
  1476. - using namespace meshopt;
  1477. -
  1478. assert(index_count % 3 == 0);
  1479. assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256);
  1480. assert(vertex_positions_stride % sizeof(float) == 0);
  1481. @@ -491,13 +481,17 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1482. unsigned int* result = destination;
  1483.  
  1484. // build adjacency information
  1485. - EdgeAdjacency adjacency(index_count, vertex_count);
  1486. - buildEdgeAdjacency(adjacency, indices, index_count, vertex_count);
  1487. + EdgeAdjacency adjacency = {};
  1488. + adjacency.counts = malloc(vertex_count * sizeof(unsigned int));
  1489. + adjacency.offsets = malloc(vertex_count * sizeof(unsigned int));
  1490. + adjacency.data = malloc(index_count * sizeof(unsigned int));
  1491. +
  1492. + buildEdgeAdjacency(&adjacency, indices, index_count, vertex_count);
  1493.  
  1494. // build position remap that maps each vertex to the one with identical position
  1495. - meshopt_Buffer<unsigned int> remap(vertex_count);
  1496. - meshopt_Buffer<unsigned int> reverse_remap(vertex_count);
  1497. - buildPositionRemap(remap.data, reverse_remap.data, vertex_positions_data, vertex_count, vertex_positions_stride);
  1498. + unsigned int* remap = malloc(vertex_count * sizeof(unsigned int));
  1499. + unsigned int* reverse_remap = malloc(vertex_count * sizeof(unsigned int));
  1500. + buildPositionRemap(remap, reverse_remap, vertex_positions_data, vertex_count, vertex_positions_stride);
  1501.  
  1502. // TODO: maybe make this an option? this disables seam awareness
  1503. // for (size_t i = 0; i < vertex_count; ++i) remap[i] = reverse_remap[i] = unsigned(i);
  1504. @@ -505,11 +499,11 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1505. size_t lockedstats[4] = {};
  1506.  
  1507. // classify vertices; vertex kind determines collapse rules, see kCanCollapse
  1508. - meshopt_Buffer<unsigned char> vertex_kind(vertex_count);
  1509. - classifyVertices(vertex_kind.data, vertex_count, adjacency, remap.data, reverse_remap.data, lockedstats);
  1510. + unsigned char* vertex_kind = malloc(vertex_count);
  1511. + classifyVertices(vertex_kind, vertex_count, &adjacency, remap, reverse_remap, lockedstats);
  1512.  
  1513. if (meshopt_simplifyDebugKind)
  1514. - memcpy(meshopt_simplifyDebugKind, vertex_kind.data, vertex_count);
  1515. + memcpy(meshopt_simplifyDebugKind, vertex_kind, vertex_count);
  1516.  
  1517. #if TRACE
  1518. size_t unique_positions = 0;
  1519. @@ -530,7 +524,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1520.  
  1521. size_t vertex_stride_float = vertex_positions_stride / sizeof(float);
  1522.  
  1523. - meshopt_Buffer<Vector3> vertex_positions(vertex_count);
  1524. + Vector3* vertex_positions = malloc(vertex_count * sizeof(Vector3));
  1525.  
  1526. // copy positions to make code slightly simpler and improve cache efficiency
  1527. for (size_t i = 0; i < vertex_count; ++i)
  1528. @@ -542,8 +536,8 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1529. vertex_positions[i].z = v[2];
  1530. }
  1531.  
  1532. - meshopt_Buffer<Quadric> vertex_quadrics(vertex_count);
  1533. - memset(vertex_quadrics.data, 0, vertex_count * sizeof(Quadric));
  1534. + Quadric* vertex_quadrics = malloc(vertex_count * sizeof(Quadric));
  1535. + memset(vertex_quadrics, 0, vertex_count * sizeof(Quadric));
  1536.  
  1537. // face quadrics
  1538. for (size_t i = 0; i < index_count; i += 3)
  1539. @@ -556,11 +550,11 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1540. // assert(i0 != i1 && i0 != i2 && i1 != i2);
  1541.  
  1542. Quadric Q;
  1543. - quadricFromTriangle(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2]);
  1544. + quadricFromTriangle(&Q, &vertex_positions[i0], &vertex_positions[i1], &vertex_positions[i2]);
  1545.  
  1546. - quadricAdd(vertex_quadrics[remap[i0]], Q);
  1547. - quadricAdd(vertex_quadrics[remap[i1]], Q);
  1548. - quadricAdd(vertex_quadrics[remap[i2]], Q);
  1549. + quadricAdd(&vertex_quadrics[remap[i0]], &Q);
  1550. + quadricAdd(&vertex_quadrics[remap[i1]], &Q);
  1551. + quadricAdd(&vertex_quadrics[remap[i2]], &Q);
  1552. }
  1553.  
  1554. // edge quadrics for boundary edges
  1555. @@ -578,7 +572,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1556. if (vertex_kind[i0] != Kind_Border && vertex_kind[i0] != Kind_Seam)
  1557. continue;
  1558.  
  1559. - if (findEdge(adjacency, i1, i0))
  1560. + if (findEdge(&adjacency, i1, i0))
  1561. continue;
  1562.  
  1563. unsigned int i2 = indices[i + next[next[e]]];
  1564. @@ -589,10 +583,10 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1565. float edgeWeight = vertex_kind[i0] == Kind_Seam ? 1.f : 10.f;
  1566.  
  1567. Quadric Q;
  1568. - quadricFromTriangleEdge(Q, vertex_positions[i0], vertex_positions[i1], vertex_positions[i2], edgeWeight);
  1569. + quadricFromTriangleEdge(&Q, &vertex_positions[i0], &vertex_positions[i1], &vertex_positions[i2], edgeWeight);
  1570.  
  1571. - quadricAdd(vertex_quadrics[remap[i0]], Q);
  1572. - quadricAdd(vertex_quadrics[remap[i1]], Q);
  1573. + quadricAdd(&vertex_quadrics[remap[i0]], &Q);
  1574. + quadricAdd(&vertex_quadrics[remap[i1]], &Q);
  1575.  
  1576. boundary++;
  1577. }
  1578. @@ -610,10 +604,10 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1579. size_t pass_count = 0;
  1580. float worst_error = 0;
  1581.  
  1582. - meshopt_Buffer<Collapse> edge_collapses(index_count);
  1583. - meshopt_Buffer<unsigned int> collapse_order(index_count);
  1584. - meshopt_Buffer<unsigned int> collapse_remap(vertex_count);
  1585. - meshopt_Buffer<char> collapse_locked(vertex_count);
  1586. + Collapse* edge_collapses = malloc(index_count * sizeof(unsigned int));
  1587. + unsigned int* collapse_order = malloc(index_count * sizeof(unsigned int));
  1588. + unsigned int* collapse_remap = malloc(vertex_count * sizeof(unsigned int));
  1589. + char* collapse_locked = malloc(vertex_count);
  1590.  
  1591. while (index_count > target_index_count)
  1592. {
  1593. @@ -640,8 +634,8 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1594. if (vertex_kind[i0] == vertex_kind[i1])
  1595. {
  1596. // TODO: Garland97 uses Q1+Q2 for error estimation; here we asssume that V1 produces zero error for Q1 but it actually gets larger with more collapses
  1597. - Collapse c01 = {i0, i1, {quadricError(vertex_quadrics[remap[i0]], vertex_positions[i1])}};
  1598. - Collapse c10 = {i1, i0, {quadricError(vertex_quadrics[remap[i1]], vertex_positions[i0])}};
  1599. + Collapse c01 = {i0, i1, {quadricError(&vertex_quadrics[remap[i0]], &vertex_positions[i1])}};
  1600. + Collapse c10 = {i1, i0, {quadricError(&vertex_quadrics[remap[i1]], &vertex_positions[i0])}};
  1601. Collapse c = c01.error <= c10.error ? c01 : c10;
  1602. assert(c.error >= 0);
  1603.  
  1604. @@ -649,7 +643,7 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1605. }
  1606. else
  1607. {
  1608. - Collapse c = {i0, i1, {quadricError(vertex_quadrics[remap[i0]], vertex_positions[i1])}};
  1609. + Collapse c = {i0, i1, {quadricError(&vertex_quadrics[remap[i0]], &vertex_positions[i1])}};
  1610. assert(c.error >= 0);
  1611.  
  1612. edge_collapses[edge_collapse_count++] = c;
  1613. @@ -661,14 +655,14 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1614. if (edge_collapse_count == 0)
  1615. break;
  1616.  
  1617. - sortEdgeCollapses(collapse_order.data, edge_collapses.data, edge_collapse_count);
  1618. + sortEdgeCollapses(collapse_order, edge_collapses, edge_collapse_count);
  1619.  
  1620. for (size_t i = 0; i < vertex_count; ++i)
  1621. {
  1622. - collapse_remap[i] = unsigned(i);
  1623. + collapse_remap[i] = (unsigned)(i);
  1624. }
  1625.  
  1626. - memset(collapse_locked.data, 0, vertex_count);
  1627. + memset(collapse_locked, 0, vertex_count);
  1628.  
  1629. // each collapse removes 2 triangles
  1630. size_t edge_collapse_goal = (index_count - target_index_count) / 6 + 1;
  1631. @@ -681,15 +675,15 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1632.  
  1633. for (size_t i = 0; i < edge_collapse_count; ++i)
  1634. {
  1635. - const Collapse& c = edge_collapses[collapse_order[i]];
  1636. + const Collapse* c = &edge_collapses[collapse_order[i]];
  1637.  
  1638. - unsigned int r0 = remap[c.v0];
  1639. - unsigned int r1 = remap[c.v1];
  1640. + unsigned int r0 = remap[c->v0];
  1641. + unsigned int r1 = remap[c->v1];
  1642.  
  1643. if (collapse_locked[r0] || collapse_locked[r1])
  1644. continue;
  1645.  
  1646. - if (c.error > error_limit)
  1647. + if (c->error > error_limit)
  1648. break;
  1649.  
  1650. #if TRACE > 1
  1651. @@ -702,32 +696,32 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1652. assert(collapse_remap[r0] == r0);
  1653. assert(collapse_remap[r1] == r1);
  1654.  
  1655. - quadricAdd(vertex_quadrics[r1], vertex_quadrics[r0]);
  1656. + quadricAdd(&vertex_quadrics[r1], &vertex_quadrics[r0]);
  1657.  
  1658. - if (vertex_kind[c.v0] == Kind_Seam)
  1659. + if (vertex_kind[c->v0] == Kind_Seam)
  1660. {
  1661. // remap v0 to v1 and seam pair of v0 to seam pair of v1
  1662. - unsigned int s0 = c.v0 == r0 ? reverse_remap[r0] : r0;
  1663. - unsigned int s1 = c.v1 == r1 ? reverse_remap[r1] : r1;
  1664. + unsigned int s0 = c->v0 == r0 ? reverse_remap[r0] : r0;
  1665. + unsigned int s1 = c->v1 == r1 ? reverse_remap[r1] : r1;
  1666.  
  1667. - assert(s0 != ~0u && s0 != c.v0);
  1668. - assert(s1 != ~0u && s1 != c.v1);
  1669. + assert(s0 != ~0u && s0 != c->v0);
  1670. + assert(s1 != ~0u && s1 != c->v1);
  1671.  
  1672. - collapse_remap[c.v0] = c.v1;
  1673. + collapse_remap[c->v0] = c->v1;
  1674. collapse_remap[s0] = s1;
  1675. }
  1676. else
  1677. {
  1678. - assert(c.v0 == r0 && reverse_remap[r0] == r0);
  1679. + assert(c->v0 == r0 && reverse_remap[r0] == r0);
  1680.  
  1681. - collapse_remap[c.v0] = c.v1;
  1682. + collapse_remap[c->v0] = c->v1;
  1683. }
  1684.  
  1685. collapse_locked[r0] = 1;
  1686. collapse_locked[r1] = 1;
  1687.  
  1688. collapses++;
  1689. - pass_error = c.error;
  1690. + pass_error = c->error;
  1691.  
  1692. if (collapses >= edge_collapse_goal)
  1693. break;
  1694. @@ -796,5 +790,18 @@ size_t meshopt_simplify(unsigned int* destination, const unsigned int* indices,
  1695. printf("locked collapses %d -> %d: %d\n", k0, k1, int(locked_collapses[k0][k1]));
  1696. #endif
  1697.  
  1698. + free(collapse_locked);
  1699. + free(collapse_remap);
  1700. + free(collapse_order);
  1701. + free(edge_collapses);
  1702. + free(vertex_quadrics);
  1703. + free(vertex_positions);
  1704. + free(vertex_kind);
  1705. + free(reverse_remap);
  1706. + free(remap);
  1707. + free(adjacency.data);
  1708. + free(adjacency.offsets);
  1709. + free(adjacency.counts);
  1710. +
  1711. return index_count;
  1712. }
  1713. diff --git a/src/stripifier.cpp b/src/stripifier.cpp
  1714. index e08189d..8493e7c 100644
  1715. --- a/src/stripifier.cpp
  1716. +++ b/src/stripifier.cpp
  1717. @@ -4,9 +4,6 @@
  1718. #include <limits.h>
  1719. #include <string.h>
  1720.  
  1721. -namespace meshopt
  1722. -{
  1723. -
  1724. static unsigned int findStripFirst(const unsigned int buffer[][3], unsigned int buffer_size, const unsigned int* valence)
  1725. {
  1726. unsigned int index = 0;
  1727. @@ -19,7 +16,7 @@ static unsigned int findStripFirst(const unsigned int buffer[][3], unsigned int
  1728.  
  1729. if (v < iv)
  1730. {
  1731. - index = unsigned(i);
  1732. + index = (unsigned)(i);
  1733. iv = v;
  1734. }
  1735. }
  1736. @@ -34,26 +31,22 @@ static int findStripNext(const unsigned int buffer[][3], unsigned int buffer_siz
  1737. unsigned int a = buffer[i][0], b = buffer[i][1], c = buffer[i][2];
  1738.  
  1739. if (e0 == a && e1 == b)
  1740. - return (int(i) << 2) | 2;
  1741. + return ((int)(i) << 2) | 2;
  1742. else if (e0 == b && e1 == c)
  1743. - return (int(i) << 2) | 0;
  1744. + return ((int)(i) << 2) | 0;
  1745. else if (e0 == c && e1 == a)
  1746. - return (int(i) << 2) | 1;
  1747. + return ((int)(i) << 2) | 1;
  1748. }
  1749.  
  1750. return -1;
  1751. }
  1752.  
  1753. -} // namespace meshopt
  1754. -
  1755. size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count)
  1756. {
  1757. assert(destination != indices);
  1758. assert(index_count % 3 == 0);
  1759.  
  1760. - using namespace meshopt;
  1761. -
  1762. - const size_t buffer_capacity = 8;
  1763. + enum { buffer_capacity = 8 };
  1764.  
  1765. unsigned int buffer[buffer_capacity][3] = {};
  1766. unsigned int buffer_size = 0;
  1767. @@ -66,8 +59,8 @@ size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices,
  1768. size_t strip_size = 0;
  1769.  
  1770. // compute vertex valence; this is used to prioritize starting triangle for strips
  1771. - meshopt_Buffer<unsigned int> valence(vertex_count);
  1772. - memset(valence.data, 0, vertex_count * sizeof(unsigned int));
  1773. + unsigned int* valence = malloc(vertex_count * sizeof(unsigned int));
  1774. + memset(valence, 0, vertex_count * sizeof(unsigned int));
  1775.  
  1776. for (size_t i = 0; i < index_count; ++i)
  1777. {
  1778. @@ -81,7 +74,7 @@ size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices,
  1779.  
  1780. while (buffer_size > 0 || index_offset < index_count)
  1781. {
  1782. - assert(next < 0 || (size_t(next >> 2) < buffer_size && (next & 3) < 3));
  1783. + assert(next < 0 || ((size_t)(next >> 2) < buffer_size && (next & 3) < 3));
  1784.  
  1785. // fill triangle buffer
  1786. while (buffer_size < buffer_capacity && index_offset < index_count)
  1787. @@ -208,6 +201,8 @@ size_t meshopt_stripify(unsigned int* destination, const unsigned int* indices,
  1788. }
  1789. }
  1790.  
  1791. + free(valence);
  1792. +
  1793. return strip_size;
  1794. }
  1795.  
  1796. diff --git a/src/vcacheanalyzer.cpp b/src/vcacheanalyzer.cpp
  1797. index c673352..d7712d9 100644
  1798. --- a/src/vcacheanalyzer.cpp
  1799. +++ b/src/vcacheanalyzer.cpp
  1800. @@ -4,19 +4,19 @@
  1801. #include <assert.h>
  1802. #include <string.h>
  1803.  
  1804. -meshopt_VertexCacheStatistics meshopt_analyzeVertexCache(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int primgroup_size)
  1805. +struct meshopt_VertexCacheStatistics meshopt_analyzeVertexCache(const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size, unsigned int warp_size, unsigned int primgroup_size)
  1806. {
  1807. assert(index_count % 3 == 0);
  1808. assert(cache_size >= 3);
  1809. assert(warp_size == 0 || warp_size >= 3);
  1810.  
  1811. - meshopt_VertexCacheStatistics result = {};
  1812. + struct meshopt_VertexCacheStatistics result = {};
  1813.  
  1814. unsigned int warp_offset = 0;
  1815. unsigned int primgroup_offset = 0;
  1816.  
  1817. - meshopt_Buffer<unsigned int> cache_timestamps(vertex_count);
  1818. - memset(cache_timestamps.data, 0, vertex_count * sizeof(unsigned int));
  1819. + unsigned int* cache_timestamps = malloc(vertex_count * sizeof(unsigned int));
  1820. + memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
  1821.  
  1822. unsigned int timestamp = cache_size + 1;
  1823.  
  1824. @@ -64,8 +64,10 @@ meshopt_VertexCacheStatistics meshopt_analyzeVertexCache(const unsigned int* ind
  1825.  
  1826. result.warps_executed += warp_offset > 0;
  1827.  
  1828. - result.acmr = index_count == 0 ? 0 : float(result.vertices_transformed) / float(index_count / 3);
  1829. - result.atvr = unique_vertex_count == 0 ? 0 : float(result.vertices_transformed) / float(unique_vertex_count);
  1830. + result.acmr = index_count == 0 ? 0 : (float)(result.vertices_transformed) / (float)(index_count / 3);
  1831. + result.atvr = unique_vertex_count == 0 ? 0 : (float)(result.vertices_transformed) / (float)(unique_vertex_count);
  1832. +
  1833. + free(cache_timestamps);
  1834.  
  1835. return result;
  1836. }
  1837. diff --git a/src/vcacheoptimizer.cpp b/src/vcacheoptimizer.cpp
  1838. index 865d5a2..ac1aacc 100644
  1839. --- a/src/vcacheoptimizer.cpp
  1840. +++ b/src/vcacheoptimizer.cpp
  1841. @@ -8,11 +8,9 @@
  1842. // This work is based on:
  1843. // Tom Forsyth. Linear-Speed Vertex Cache Optimisation. 2006
  1844. // Pedro Sander, Diego Nehab and Joshua Barczak. Fast Triangle Reordering for Vertex Locality and Reduced Overdraw. 2007
  1845. -namespace meshopt
  1846. -{
  1847.  
  1848. -const size_t max_cache_size = 16;
  1849. -const size_t max_valence = 8;
  1850. +enum { max_cache_size = 16 };
  1851. +enum { max_valence = 8 };
  1852.  
  1853. static const float vertex_score_table_cache[1 + max_cache_size] = {
  1854. 0.f,
  1855. @@ -22,32 +20,25 @@ static const float vertex_score_table_live[1 + max_valence] = {
  1856. 0.f,
  1857. 0.994f, 0.721f, 0.479f, 0.423f, 0.174f, 0.080f, 0.249f, 0.056f};
  1858.  
  1859. -struct TriangleAdjacency
  1860. +typedef struct TriangleAdjacency
  1861. {
  1862. - meshopt_Buffer<unsigned int> counts;
  1863. - meshopt_Buffer<unsigned int> offsets;
  1864. - meshopt_Buffer<unsigned int> data;
  1865. -
  1866. - TriangleAdjacency(size_t index_count, size_t vertex_count)
  1867. - : counts(vertex_count)
  1868. - , offsets(vertex_count)
  1869. - , data(index_count)
  1870. - {
  1871. - }
  1872. -};
  1873. + unsigned int* counts;
  1874. + unsigned int* offsets;
  1875. + unsigned int* data;
  1876. +} TriangleAdjacency;
  1877.  
  1878. -static void buildTriangleAdjacency(TriangleAdjacency& adjacency, const unsigned int* indices, size_t index_count, size_t vertex_count)
  1879. +static void buildTriangleAdjacency(TriangleAdjacency* adjacency, const unsigned int* indices, size_t index_count, size_t vertex_count)
  1880. {
  1881. size_t face_count = index_count / 3;
  1882.  
  1883. // fill triangle counts
  1884. - memset(adjacency.counts.data, 0, vertex_count * sizeof(unsigned int));
  1885. + memset(adjacency->counts, 0, vertex_count * sizeof(unsigned int));
  1886.  
  1887. for (size_t i = 0; i < index_count; ++i)
  1888. {
  1889. assert(indices[i] < vertex_count);
  1890.  
  1891. - adjacency.counts[indices[i]]++;
  1892. + adjacency->counts[indices[i]]++;
  1893. }
  1894.  
  1895. // fill offset table
  1896. @@ -55,8 +46,8 @@ static void buildTriangleAdjacency(TriangleAdjacency& adjacency, const unsigned
  1897.  
  1898. for (size_t i = 0; i < vertex_count; ++i)
  1899. {
  1900. - adjacency.offsets[i] = offset;
  1901. - offset += adjacency.counts[i];
  1902. + adjacency->offsets[i] = offset;
  1903. + offset += adjacency->counts[i];
  1904. }
  1905.  
  1906. assert(offset == index_count);
  1907. @@ -66,38 +57,38 @@ static void buildTriangleAdjacency(TriangleAdjacency& adjacency, const unsigned
  1908. {
  1909. unsigned int a = indices[i * 3 + 0], b = indices[i * 3 + 1], c = indices[i * 3 + 2];
  1910.  
  1911. - adjacency.data[adjacency.offsets[a]++] = unsigned(i);
  1912. - adjacency.data[adjacency.offsets[b]++] = unsigned(i);
  1913. - adjacency.data[adjacency.offsets[c]++] = unsigned(i);
  1914. + adjacency->data[adjacency->offsets[a]++] = (unsigned)(i);
  1915. + adjacency->data[adjacency->offsets[b]++] = (unsigned)(i);
  1916. + adjacency->data[adjacency->offsets[c]++] = (unsigned)(i);
  1917. }
  1918.  
  1919. // fix offsets that have been disturbed by the previous pass
  1920. for (size_t i = 0; i < vertex_count; ++i)
  1921. {
  1922. - assert(adjacency.offsets[i] >= adjacency.counts[i]);
  1923. + assert(adjacency->offsets[i] >= adjacency->counts[i]);
  1924.  
  1925. - adjacency.offsets[i] -= adjacency.counts[i];
  1926. + adjacency->offsets[i] -= adjacency->counts[i];
  1927. }
  1928. }
  1929.  
  1930. -static unsigned int getNextVertexDeadEnd(const unsigned int* dead_end, unsigned int& dead_end_top, unsigned int& input_cursor, const unsigned int* live_triangles, size_t vertex_count)
  1931. +static unsigned int getNextVertexDeadEnd(const unsigned int* dead_end, unsigned int* dead_end_top, unsigned int* input_cursor, const unsigned int* live_triangles, size_t vertex_count)
  1932. {
  1933. // check dead-end stack
  1934. - while (dead_end_top)
  1935. + while (*dead_end_top)
  1936. {
  1937. - unsigned int vertex = dead_end[--dead_end_top];
  1938. + unsigned int vertex = dead_end[--*dead_end_top];
  1939.  
  1940. if (live_triangles[vertex] > 0)
  1941. return vertex;
  1942. }
  1943.  
  1944. // input order
  1945. - while (input_cursor < vertex_count)
  1946. + while (*input_cursor < vertex_count)
  1947. {
  1948. - if (live_triangles[input_cursor] > 0)
  1949. - return input_cursor;
  1950. + if (live_triangles[*input_cursor] > 0)
  1951. + return *input_cursor;
  1952.  
  1953. - ++input_cursor;
  1954. + ++*input_cursor;
  1955. }
  1956.  
  1957. return ~0u;
  1958. @@ -136,33 +127,29 @@ static unsigned int getNextVertexNeighbour(const unsigned int* next_candidates_b
  1959.  
  1960. static float vertexScore(int cache_position, unsigned int live_triangles)
  1961. {
  1962. - assert(cache_position >= -1 && cache_position < int(max_cache_size));
  1963. + assert(cache_position >= -1 && cache_position < (int)(max_cache_size));
  1964.  
  1965. unsigned int live_triangles_clamped = live_triangles < max_valence ? live_triangles : max_valence;
  1966.  
  1967. return vertex_score_table_cache[1 + cache_position] + vertex_score_table_live[live_triangles_clamped];
  1968. }
  1969.  
  1970. -static unsigned int getNextTriangleDeadEnd(unsigned int& input_cursor, const char* emitted_flags, size_t face_count)
  1971. +static unsigned int getNextTriangleDeadEnd(unsigned int* input_cursor, const char* emitted_flags, size_t face_count)
  1972. {
  1973. // input order
  1974. - while (input_cursor < face_count)
  1975. + while (*input_cursor < face_count)
  1976. {
  1977. - if (!emitted_flags[input_cursor])
  1978. - return input_cursor;
  1979. + if (!emitted_flags[*input_cursor])
  1980. + return *input_cursor;
  1981.  
  1982. - ++input_cursor;
  1983. + ++*input_cursor;
  1984. }
  1985.  
  1986. return ~0u;
  1987. }
  1988.  
  1989. -} // namespace meshopt
  1990. -
  1991. void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count)
  1992. {
  1993. - using namespace meshopt;
  1994. -
  1995. assert(index_count % 3 == 0);
  1996.  
  1997. // guard for empty meshes
  1998. @@ -170,13 +157,13 @@ void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int*
  1999. return;
  2000.  
  2001. // support in-place optimization
  2002. - meshopt_Buffer<unsigned int> indices_copy;
  2003. + unsigned int* indices_copy = 0;
  2004.  
  2005. if (destination == indices)
  2006. {
  2007. - indices_copy.allocate(index_count);
  2008. - memcpy(indices_copy.data, indices, index_count * sizeof(unsigned int));
  2009. - indices = indices_copy.data;
  2010. + indices_copy = malloc(index_count * sizeof(unsigned int));
  2011. + memcpy(indices_copy, indices, index_count * sizeof(unsigned int));
  2012. + indices = indices_copy;
  2013. }
  2014.  
  2015. unsigned int cache_size = 16;
  2016. @@ -185,19 +172,22 @@ void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int*
  2017. size_t face_count = index_count / 3;
  2018.  
  2019. // build adjacency information
  2020. - TriangleAdjacency adjacency(index_count, vertex_count);
  2021. - buildTriangleAdjacency(adjacency, indices, index_count, vertex_count);
  2022. + TriangleAdjacency adjacency = {};
  2023. + adjacency.counts = malloc(vertex_count * sizeof(unsigned int));
  2024. + adjacency.offsets = malloc(vertex_count * sizeof(unsigned int));
  2025. + adjacency.data = malloc(index_count * sizeof(unsigned int));
  2026. + buildTriangleAdjacency(&adjacency, indices, index_count, vertex_count);
  2027.  
  2028. // live triangle counts
  2029. - meshopt_Buffer<unsigned int> live_triangles(vertex_count);
  2030. - memcpy(live_triangles.data, adjacency.counts.data, vertex_count * sizeof(unsigned int));
  2031. + unsigned int* live_triangles = malloc(vertex_count * sizeof(unsigned int));
  2032. + memcpy(live_triangles, adjacency.counts, vertex_count * sizeof(unsigned int));
  2033.  
  2034. // emitted flags
  2035. - meshopt_Buffer<char> emitted_flags(face_count);
  2036. - memset(emitted_flags.data, 0, face_count);
  2037. + char* emitted_flags = malloc(face_count);
  2038. + memset(emitted_flags, 0, face_count);
  2039.  
  2040. // compute initial vertex scores
  2041. - meshopt_Buffer<float> vertex_scores(vertex_count);
  2042. + float* vertex_scores = malloc(vertex_count * sizeof(float));
  2043.  
  2044. for (size_t i = 0; i < vertex_count; ++i)
  2045. {
  2046. @@ -205,7 +195,7 @@ void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int*
  2047. }
  2048.  
  2049. // compute triangle scores
  2050. - meshopt_Buffer<float> triangle_scores(face_count);
  2051. + float* triangle_scores = malloc(face_count * sizeof(float));
  2052.  
  2053. for (size_t i = 0; i < face_count; ++i)
  2054. {
  2055. @@ -300,7 +290,7 @@ void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int*
  2056. {
  2057. unsigned int index = cache[i];
  2058.  
  2059. - int cache_position = i >= cache_size ? -1 : int(i);
  2060. + int cache_position = i >= cache_size ? -1 : (int)(i);
  2061.  
  2062. // update vertex score
  2063. float score = vertexScore(cache_position, live_triangles[index]);
  2064. @@ -335,18 +325,25 @@ void meshopt_optimizeVertexCache(unsigned int* destination, const unsigned int*
  2065.  
  2066. if (current_triangle == ~0u)
  2067. {
  2068. - current_triangle = getNextTriangleDeadEnd(input_cursor, &emitted_flags[0], face_count);
  2069. + current_triangle = getNextTriangleDeadEnd(&input_cursor, &emitted_flags[0], face_count);
  2070. }
  2071. }
  2072.  
  2073. assert(input_cursor == face_count);
  2074. assert(output_triangle == face_count);
  2075. +
  2076. + free(triangle_scores);
  2077. + free(vertex_scores);
  2078. + free(emitted_flags);
  2079. + free(live_triangles);
  2080. + free(adjacency.data);
  2081. + free(adjacency.offsets);
  2082. + free(adjacency.counts);
  2083. + free(indices_copy);
  2084. }
  2085.  
  2086. void meshopt_optimizeVertexCacheFifo(unsigned int* destination, const unsigned int* indices, size_t index_count, size_t vertex_count, unsigned int cache_size)
  2087. {
  2088. - using namespace meshopt;
  2089. -
  2090. assert(index_count % 3 == 0);
  2091. assert(cache_size >= 3);
  2092.  
  2093. @@ -355,36 +352,39 @@ void meshopt_optimizeVertexCacheFifo(unsigned int* destination, const unsigned i
  2094. return;
  2095.  
  2096. // support in-place optimization
  2097. - meshopt_Buffer<unsigned int> indices_copy;
  2098. + unsigned int* indices_copy = 0;
  2099.  
  2100. if (destination == indices)
  2101. {
  2102. - indices_copy.allocate(index_count);
  2103. - memcpy(indices_copy.data, indices, index_count * sizeof(unsigned int));
  2104. - indices = indices_copy.data;
  2105. + indices_copy = malloc(index_count * sizeof(unsigned int));
  2106. + memcpy(indices_copy, indices, index_count * sizeof(unsigned int));
  2107. + indices = indices_copy;
  2108. }
  2109.  
  2110. size_t face_count = index_count / 3;
  2111.  
  2112. // build adjacency information
  2113. - TriangleAdjacency adjacency(index_count, vertex_count);
  2114. - buildTriangleAdjacency(adjacency, indices, index_count, vertex_count);
  2115. + TriangleAdjacency adjacency = {};
  2116. + adjacency.counts = malloc(vertex_count * sizeof(unsigned int));
  2117. + adjacency.offsets = malloc(vertex_count * sizeof(unsigned int));
  2118. + adjacency.data = malloc(index_count * sizeof(unsigned int));
  2119. + buildTriangleAdjacency(&adjacency, indices, index_count, vertex_count);
  2120.  
  2121. // live triangle counts
  2122. - meshopt_Buffer<unsigned int> live_triangles(vertex_count);
  2123. - memcpy(live_triangles.data, adjacency.counts.data, vertex_count * sizeof(unsigned int));
  2124. + unsigned int* live_triangles = malloc(vertex_count * sizeof(unsigned int));
  2125. + memcpy(live_triangles, adjacency.counts, vertex_count * sizeof(unsigned int));
  2126.  
  2127. // cache time stamps
  2128. - meshopt_Buffer<unsigned int> cache_timestamps(vertex_count);
  2129. - memset(cache_timestamps.data, 0, vertex_count * sizeof(unsigned int));
  2130. + unsigned int* cache_timestamps = malloc(vertex_count * sizeof(unsigned int));
  2131. + memset(cache_timestamps, 0, vertex_count * sizeof(unsigned int));
  2132.  
  2133. // dead-end stack
  2134. - meshopt_Buffer<unsigned int> dead_end(index_count);
  2135. + unsigned int* dead_end = malloc(index_count * sizeof(unsigned int));
  2136. unsigned int dead_end_top = 0;
  2137.  
  2138. // emitted flags
  2139. - meshopt_Buffer<char> emitted_flags(face_count);
  2140. - memset(emitted_flags.data, 0, face_count);
  2141. + char* emitted_flags = malloc(face_count);
  2142. + memset(emitted_flags, 0, face_count);
  2143.  
  2144. unsigned int current_vertex = 0;
  2145.  
  2146. @@ -450,9 +450,18 @@ void meshopt_optimizeVertexCacheFifo(unsigned int* destination, const unsigned i
  2147.  
  2148. if (current_vertex == ~0u)
  2149. {
  2150. - current_vertex = getNextVertexDeadEnd(&dead_end[0], dead_end_top, input_cursor, &live_triangles[0], vertex_count);
  2151. + current_vertex = getNextVertexDeadEnd(&dead_end[0], &dead_end_top, &input_cursor, &live_triangles[0], vertex_count);
  2152. }
  2153. }
  2154.  
  2155. assert(output_triangle == face_count);
  2156. +
  2157. + free(emitted_flags);
  2158. + free(dead_end);
  2159. + free(cache_timestamps);
  2160. + free(live_triangles);
  2161. + free(adjacency.data);
  2162. + free(adjacency.offsets);
  2163. + free(adjacency.counts);
  2164. + free(indices_copy);
  2165. }
  2166. diff --git a/src/vertexcodec.cpp b/src/vertexcodec.cpp
  2167. index ba9d546..28d8391 100644
  2168. --- a/src/vertexcodec.cpp
  2169. +++ b/src/vertexcodec.cpp
  2170. @@ -26,9 +26,6 @@
  2171. #include <arm_neon.h>
  2172. #endif
  2173.  
  2174. -namespace meshopt
  2175. -{
  2176. -
  2177. const unsigned char kVertexHeader = 0xa0;
  2178.  
  2179. const size_t kVertexBlockSizeBytes = 8192;
  2180. @@ -72,7 +69,7 @@ static size_t encodeBytesGroupMeasure(const unsigned char* buffer, int bits)
  2181. assert(bits >= 1 && bits <= 8);
  2182.  
  2183. if (bits == 1)
  2184. - return encodeBytesGroupZero(buffer) ? 0 : size_t(-1);
  2185. + return encodeBytesGroupZero(buffer) ? 0 : (size_t)(-1);
  2186.  
  2187. if (bits == 8)
  2188. return kByteGroupSize;
  2189. @@ -142,7 +139,7 @@ static unsigned char* encodeBytes(unsigned char* data, unsigned char* data_end,
  2190. // round number of groups to 4 to get number of header bytes
  2191. size_t header_size = (buffer_size / kByteGroupSize + 3) / 4;
  2192.  
  2193. - if (size_t(data_end - data) < header_size)
  2194. + if ((size_t)(data_end - data) < header_size)
  2195. return 0;
  2196.  
  2197. data += header_size;
  2198. @@ -151,7 +148,7 @@ static unsigned char* encodeBytes(unsigned char* data, unsigned char* data_end,
  2199.  
  2200. for (size_t i = 0; i < buffer_size; i += kByteGroupSize)
  2201. {
  2202. - if (size_t(data_end - data) < kTailMaxSize)
  2203. + if ((size_t)(data_end - data) < kTailMaxSize)
  2204. return 0;
  2205.  
  2206. int best_bits = 8;
  2207. @@ -278,14 +275,14 @@ static const unsigned char* decodeBytes(const unsigned char* data, const unsigne
  2208. // round number of groups to 4 to get number of header bytes
  2209. size_t header_size = (buffer_size / kByteGroupSize + 3) / 4;
  2210.  
  2211. - if (size_t(data_end - data) < header_size)
  2212. + if ((size_t)(data_end - data) < header_size)
  2213. return 0;
  2214.  
  2215. data += header_size;
  2216.  
  2217. for (size_t i = 0; i < buffer_size; i += kByteGroupSize)
  2218. {
  2219. - if (size_t(data_end - data) < kTailMaxSize)
  2220. + if ((size_t)(data_end - data) < kTailMaxSize)
  2221. return 0;
  2222.  
  2223. size_t header_offset = i / kByteGroupSize;
  2224. @@ -609,7 +606,7 @@ static const unsigned char* decodeBytesSimd(const unsigned char* data, const uns
  2225. // round number of groups to 4 to get number of header bytes
  2226. size_t header_size = (buffer_size / kByteGroupSize + 3) / 4;
  2227.  
  2228. - if (size_t(data_end - data) < header_size)
  2229. + if ((size_t)(data_end - data) < header_size)
  2230. return 0;
  2231.  
  2232. data += header_size;
  2233. @@ -617,7 +614,7 @@ static const unsigned char* decodeBytesSimd(const unsigned char* data, const uns
  2234. size_t i = 0;
  2235.  
  2236. // fast-path: process 4 groups at a time, do a shared bounds check - each group reads <=32b
  2237. - for (; i + kByteGroupSize * 4 <= buffer_size && size_t(data_end - data) >= kTailMaxSize * 4; i += kByteGroupSize * 4)
  2238. + for (; i + kByteGroupSize * 4 <= buffer_size && (size_t)(data_end - data) >= kTailMaxSize * 4; i += kByteGroupSize * 4)
  2239. {
  2240. size_t header_offset = i / kByteGroupSize;
  2241. unsigned char header_byte = header[header_offset / 4];
  2242. @@ -631,7 +628,7 @@ static const unsigned char* decodeBytesSimd(const unsigned char* data, const uns
  2243. // slow-path: process remaining groups
  2244. for (; i < buffer_size; i += kByteGroupSize)
  2245. {
  2246. - if (size_t(data_end - data) < kTailMaxSize)
  2247. + if ((size_t)(data_end - data) < kTailMaxSize)
  2248. return 0;
  2249.  
  2250. size_t header_offset = i / kByteGroupSize;
  2251. @@ -735,21 +732,17 @@ static const unsigned char* decodeVertexBlockSimd(const unsigned char* data, con
  2252. }
  2253. #endif
  2254.  
  2255. -} // namespace meshopt
  2256. -
  2257. size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, const void* vertices, size_t vertex_count, size_t vertex_size)
  2258. {
  2259. - using namespace meshopt;
  2260. -
  2261. assert(vertex_size > 0 && vertex_size <= 256);
  2262. assert(vertex_size % 4 == 0);
  2263.  
  2264. - const unsigned char* vertex_data = static_cast<const unsigned char*>(vertices);
  2265. + const unsigned char* vertex_data = (const unsigned char*)(vertices);
  2266.  
  2267. unsigned char* data = buffer;
  2268. unsigned char* data_end = buffer + buffer_size;
  2269.  
  2270. - if (size_t(data_end - data) < 1 + vertex_size)
  2271. + if ((size_t)(data_end - data) < 1 + vertex_size)
  2272. return 0;
  2273.  
  2274. *data++ = kVertexHeader;
  2275. @@ -775,7 +768,7 @@ size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, con
  2276.  
  2277. size_t tail_size = vertex_size < kTailMaxSize ? kTailMaxSize : vertex_size;
  2278.  
  2279. - if (size_t(data_end - data) < tail_size)
  2280. + if ((size_t)(data_end - data) < tail_size)
  2281. return 0;
  2282.  
  2283. // write first vertex to the end of the stream and pad it to 32 bytes; this is important to simplify bounds checks in decoder
  2284. @@ -796,8 +789,6 @@ size_t meshopt_encodeVertexBuffer(unsigned char* buffer, size_t buffer_size, con
  2285.  
  2286. size_t meshopt_encodeVertexBufferBound(size_t vertex_count, size_t vertex_size)
  2287. {
  2288. - using namespace meshopt;
  2289. -
  2290. assert(vertex_size > 0 && vertex_size <= 256);
  2291. assert(vertex_size % 4 == 0);
  2292.  
  2293. @@ -814,8 +805,6 @@ size_t meshopt_encodeVertexBufferBound(size_t vertex_count, size_t vertex_size)
  2294.  
  2295. int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t vertex_size, const unsigned char* buffer, size_t buffer_size)
  2296. {
  2297. - using namespace meshopt;
  2298. -
  2299. assert(vertex_size > 0 && vertex_size <= 256);
  2300. assert(vertex_size % 4 == 0);
  2301.  
  2302. @@ -835,12 +824,12 @@ int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t ve
  2303. assert(gDecodeBytesGroupInitialized);
  2304. #endif
  2305.  
  2306. - unsigned char* vertex_data = static_cast<unsigned char*>(destination);
  2307. + unsigned char* vertex_data = (unsigned char*)(destination);
  2308.  
  2309. const unsigned char* data = buffer;
  2310. const unsigned char* data_end = buffer + buffer_size;
  2311.  
  2312. - if (size_t(data_end - data) < 1 + vertex_size)
  2313. + if ((size_t)(data_end - data) < 1 + vertex_size)
  2314. return -2;
  2315.  
  2316. if (*data++ != kVertexHeader)
  2317. @@ -866,7 +855,7 @@ int meshopt_decodeVertexBuffer(void* destination, size_t vertex_count, size_t ve
  2318.  
  2319. size_t tail_size = vertex_size < kTailMaxSize ? kTailMaxSize : vertex_size;
  2320.  
  2321. - if (size_t(data_end - data) != tail_size)
  2322. + if ((size_t)(data_end - data) != tail_size)
  2323. return -3;
  2324.  
  2325. return 0;
  2326. diff --git a/src/vfetchanalyzer.cpp b/src/vfetchanalyzer.cpp
  2327. index 8a96c0b..dc0d17e 100644
  2328. --- a/src/vfetchanalyzer.cpp
  2329. +++ b/src/vfetchanalyzer.cpp
  2330. @@ -4,18 +4,18 @@
  2331. #include <assert.h>
  2332. #include <string.h>
  2333.  
  2334. -meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const unsigned int* indices, size_t index_count, size_t vertex_count, size_t vertex_size)
  2335. +struct meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const unsigned int* indices, size_t index_count, size_t vertex_count, size_t vertex_size)
  2336. {
  2337. assert(index_count % 3 == 0);
  2338. assert(vertex_size > 0 && vertex_size <= 256);
  2339.  
  2340. - meshopt_VertexFetchStatistics result = {};
  2341. + struct meshopt_VertexFetchStatistics result = {};
  2342.  
  2343. - meshopt_Buffer<char> vertex_visited(vertex_count);
  2344. - memset(vertex_visited.data, 0, vertex_count);
  2345. + char* vertex_visited = malloc(vertex_count);
  2346. + memset(vertex_visited, 0, vertex_count);
  2347.  
  2348. - const size_t kCacheLine = 64;
  2349. - const size_t kCacheSize = 128 * 1024;
  2350. + enum { kCacheLine = 64 };
  2351. + enum { kCacheSize = 128 * 1024 };
  2352.  
  2353. // simple direct mapped cache; on typical mesh data this is close to 4-way cache, and this model is a gross approximation anyway
  2354. size_t cache[kCacheSize / kCacheLine] = {};
  2355. @@ -50,7 +50,9 @@ meshopt_VertexFetchStatistics meshopt_analyzeVertexFetch(const unsigned int* ind
  2356. for (size_t i = 0; i < vertex_count; ++i)
  2357. unique_vertex_count += vertex_visited[i];
  2358.  
  2359. - result.overfetch = unique_vertex_count == 0 ? 0 : float(result.bytes_fetched) / float(unique_vertex_count * vertex_size);
  2360. + result.overfetch = unique_vertex_count == 0 ? 0 : (float)(result.bytes_fetched) / (float)(unique_vertex_count * vertex_size);
  2361. +
  2362. + free(vertex_visited);
  2363.  
  2364. return result;
  2365. }
  2366. diff --git a/src/vfetchoptimizer.cpp b/src/vfetchoptimizer.cpp
  2367. index 55825a4..b9c6cb7 100644
  2368. --- a/src/vfetchoptimizer.cpp
  2369. +++ b/src/vfetchoptimizer.cpp
  2370. @@ -34,18 +34,18 @@ size_t meshopt_optimizeVertexFetch(void* destination, unsigned int* indices, siz
  2371. assert(vertex_size > 0 && vertex_size <= 256);
  2372.  
  2373. // support in-place optimization
  2374. - meshopt_Buffer<char> vertices_copy;
  2375. + char* vertices_copy = 0;
  2376.  
  2377. if (destination == vertices)
  2378. {
  2379. - vertices_copy.allocate(vertex_count * vertex_size);
  2380. - memcpy(vertices_copy.data, vertices, vertex_count * vertex_size);
  2381. - vertices = vertices_copy.data;
  2382. + vertices_copy = malloc(vertex_count * vertex_size);
  2383. + memcpy(vertices_copy, vertices, vertex_count * vertex_size);
  2384. + vertices = vertices_copy;
  2385. }
  2386.  
  2387. // build vertex remap table
  2388. - meshopt_Buffer<unsigned int> vertex_remap(vertex_count);
  2389. - memset(vertex_remap.data, -1, vertex_remap.size * sizeof(unsigned int));
  2390. + unsigned int* vertex_remap = malloc(vertex_count * sizeof(unsigned int));
  2391. + memset(vertex_remap, -1, vertex_count * sizeof(unsigned int));
  2392.  
  2393. unsigned int next_vertex = 0;
  2394.  
  2395. @@ -54,21 +54,24 @@ size_t meshopt_optimizeVertexFetch(void* destination, unsigned int* indices, siz
  2396. unsigned int index = indices[i];
  2397. assert(index < vertex_count);
  2398.  
  2399. - unsigned int& remap = vertex_remap[index];
  2400. + unsigned int* remap = &vertex_remap[index];
  2401.  
  2402. - if (remap == ~0u) // vertex was not added to destination VB
  2403. + if (*remap == ~0u) // vertex was not added to destination VB
  2404. {
  2405. // add vertex
  2406. - memcpy(static_cast<char*>(destination) + next_vertex * vertex_size, static_cast<const char*>(vertices) + index * vertex_size, vertex_size);
  2407. + memcpy((char*)(destination) + next_vertex * vertex_size, (const char*)(vertices) + index * vertex_size, vertex_size);
  2408.  
  2409. - remap = next_vertex++;
  2410. + *remap = next_vertex++;
  2411. }
  2412.  
  2413. // modify indices in place
  2414. - indices[i] = remap;
  2415. + indices[i] = *remap;
  2416. }
  2417.  
  2418. assert(next_vertex <= vertex_count);
  2419.  
  2420. + free(vertex_remap);
  2421. + free(vertices_copy);
  2422. +
  2423. return next_vertex;
  2424. }
Add Comment
Please, Sign In to add comment