345 |
386 |
|
destination[i] = remap[index]; |
346 |
387 |
|
} |
347 |
388 |
|
} |
|
389 |
+ |
|
|
390 |
+ |
void meshopt_generateTessellationIndexBuffer(unsigned int* destination, const unsigned int* indices, size_t index_count, const float* vertex_positions, size_t vertex_count, size_t vertex_positions_stride) |
|
391 |
+ |
{ |
|
392 |
+ |
using namespace meshopt; |
|
393 |
+ |
|
|
394 |
+ |
assert(index_count % 3 == 0); |
|
395 |
+ |
assert(vertex_positions_stride > 0 && vertex_positions_stride <= 256); |
|
396 |
+ |
assert(vertex_positions_stride % sizeof(float) == 0); |
|
397 |
+ |
|
|
398 |
+ |
meshopt_Allocator allocator; |
|
399 |
+ |
|
|
400 |
+ |
static const int next[3] = {1, 2, 0}; |
|
401 |
+ |
|
|
402 |
+ |
VertexHasher vertex_hasher = {reinterpret_cast<const unsigned char*>(vertex_positions), 3 * sizeof(float), vertex_positions_stride}; |
|
403 |
+ |
|
|
404 |
+ |
size_t vertex_table_size = hashBuckets(vertex_count); |
|
405 |
+ |
unsigned int* vertex_table = allocator.allocate<unsigned int>(vertex_table_size); |
|
406 |
+ |
memset(vertex_table, -1, vertex_table_size * sizeof(unsigned int)); |
|
407 |
+ |
|
|
408 |
+ |
// build position remap: for each vertex, which other (canonical) vertex does it map to? |
|
409 |
+ |
unsigned int* remap = allocator.allocate<unsigned int>(vertex_count); |
|
410 |
+ |
|
|
411 |
+ |
for (size_t i = 0; i < vertex_count; ++i) |
|
412 |
+ |
{ |
|
413 |
+ |
unsigned int index = unsigned(i); |
|
414 |
+ |
unsigned int* entry = hashLookup(vertex_table, vertex_table_size, vertex_hasher, index, ~0u); |
|
415 |
+ |
|
|
416 |
+ |
if (*entry == ~0u) |
|
417 |
+ |
*entry = index; |
|
418 |
+ |
|
|
419 |
+ |
remap[index] = *entry; |
|
420 |
+ |
} |
|
421 |
+ |
|
|
422 |
+ |
// build edge set; this stores all triangle edges but we can look these up by any other wedge |
|
423 |
+ |
EdgeHasher edge_hasher = {remap}; |
|
424 |
+ |
|
|
425 |
+ |
size_t edge_table_size = hashBuckets(index_count); |
|
426 |
+ |
unsigned long long* edge_table = allocator.allocate<unsigned long long>(edge_table_size); |
|
427 |
+ |
memset(edge_table, -1, edge_table_size * sizeof(unsigned long long)); |
|
428 |
+ |
|
|
429 |
+ |
for (size_t i = 0; i < index_count; i += 3) |
|
430 |
+ |
{ |
|
431 |
+ |
for (int e = 0; e < 3; ++e) |
|
432 |
+ |
{ |
|
433 |
+ |
unsigned int i0 = indices[i + e]; |
|
434 |
+ |
unsigned int i1 = indices[i + next[e]]; |
|
435 |
+ |
assert(i0 < vertex_count && i1 < vertex_count); |
|
436 |
+ |
|
|
437 |
+ |
unsigned long long edge = ((unsigned long long)i0 << 32) | i1; |
|
438 |
+ |
unsigned long long* entry = hashLookup(edge_table, edge_table_size, edge_hasher, edge, ~0ull); |
|
439 |
+ |
|
|
440 |
+ |
if (*entry == ~0ull) |
|
441 |
+ |
*entry = edge; |
|
442 |
+ |
} |
|
443 |
+ |
} |
|
444 |
+ |
|
|
445 |
+ |
// build resulting index buffer: 12 indices for each input triangle |
|
446 |
+ |
for (size_t i = 0; i < index_count; i += 3) |
|
447 |
+ |
{ |
|
448 |
+ |
unsigned int patch[12]; |
|
449 |
+ |
|
|
450 |
+ |
for (int e = 0; e < 3; ++e) |
|
451 |
+ |
{ |
|
452 |
+ |
unsigned int i0 = indices[i + e]; |
|
453 |
+ |
unsigned int i1 = indices[i + next[e]]; |
|
454 |
+ |
assert(i0 < vertex_count && i1 < vertex_count); |
|
455 |
+ |
|
|
456 |
+ |
// note: this refers to the opposite edge! |
|
457 |
+ |
unsigned long long edge = ((unsigned long long)i1 << 32) | i0; |
|
458 |
+ |
unsigned long long oppe = *hashLookup(edge_table, edge_table_size, edge_hasher, edge, ~0ull); |
|
459 |
+ |
|
|
460 |
+ |
// use the same edge if opposite edge doesn't exist (border) |
|
461 |
+ |
oppe = (oppe == ~0ull) ? edge : oppe; |
|
462 |
+ |
|
|
463 |
+ |
// triangle index (0, 1, 2) |
|
464 |
+ |
patch[e] = i0; |
|
465 |
+ |
|
|
466 |
+ |
// opposite edge (3, 4; 5, 6; 7, 8) |
|
467 |
+ |
patch[3 + e * 2 + 0] = unsigned(oppe); |
|
468 |
+ |
patch[3 + e * 2 + 1] = unsigned(oppe >> 32); |
|
469 |
+ |
|
|
470 |
+ |
// dominant vertex (9, 10, 11) |
|
471 |
+ |
patch[9 + e] = remap[i0]; |
|
472 |
+ |
} |
|
473 |
+ |
|
|
474 |
+ |
memcpy(destination + i * 4, patch, sizeof(patch)); |
|
475 |
+ |
} |
|
476 |
+ |
} |