72#ifndef OGT_VOXEL_MESHIFY_H__
73# define OGT_VOXEL_MESHIFY_H__
78typedef unsigned char uint8_t;
79typedef signed int int32_t;
80typedef unsigned int uint32_t;
81typedef unsigned short uint16_t;
83# define UINT32_MAX 0xFFFFFFFF
85# elif defined(_MSC_VER)
90# elif defined(__GNUC__)
95# error some fixup needed for this platform?
122 uint32_t vertex_count;
123 uint32_t index_count;
129typedef void* (*ogt_voxel_meshify_alloc_func)(
size_t size,
void* user_data);
132typedef void (*ogt_voxel_meshify_free_func)(
void* ptr,
void* user_data);
135typedef void (*ogt_voxel_simple_stream_func)(uint32_t x, uint32_t y, uint32_t z,
const ogt_mesh_vertex* vertices, uint32_t vertex_count,
const uint32_t* indices, uint32_t index_count,
void* user_data);
140 ogt_voxel_meshify_alloc_func alloc_func;
141 ogt_voxel_meshify_free_func free_func;
142 void* alloc_free_user_data;
147uint32_t ogt_face_count_from_paletted_voxels_simple(
const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z);
173void ogt_stream_from_paletted_voxels_simple(
const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z,
const ogt_mesh_rgba* pPalette, ogt_voxel_simple_stream_func stream_func,
void* pStream_func_data);
184#ifdef OGT_VOXEL_MESHIFY_IMPLEMENTATION
191struct ogt_mesh_bitset_64k
194 void clear(uint32_t max_bits)
196 if (max_bits > (8192 * 8))
197 max_bits = (8192 * 8);
198 memset(bits, 0, (max_bits + 7) / 8);
200 uint8_t is_set(uint32_t index) {
return bits[index / 8] & (1 << (index % 8)); }
201 void set(uint32_t index) { bits[index / 8] |= (1 << (index % 8)); }
202 void unset(uint32_t index) { bits[index / 8] &= ~(1 << (index % 8)); }
207 return uiSize ? (pCtx->alloc_func ? pCtx->alloc_func(uiSize, pCtx->alloc_free_user_data) : malloc(uiSize)) : NULL;
215 pCtx->free_func(pOld_ptr, pCtx->alloc_free_user_data);
222struct ogt_mesh_transform
224 float m00, m01, m02, m03;
225 float m10, m11, m12, m13;
226 float m20, m21, m22, m23;
227 float m30, m31, m32, m33;
234 ret.x = transform.m30 + (transform.m00 * vec.x) + (transform.m10 * vec.y) + (transform.m20 * vec.z);
235 ret.y = transform.m31 + (transform.m01 * vec.x) + (transform.m11 * vec.y) + (transform.m21 * vec.z);
236 ret.z = transform.m32 + (transform.m02 * vec.x) + (transform.m12 * vec.y) + (transform.m22 * vec.z);
244 ret.x = (transform.m00 * vec.x) + (transform.m10 * vec.y) + (transform.m20 * vec.z);
245 ret.y = (transform.m01 * vec.x) + (transform.m11 * vec.y) + (transform.m21 * vec.z);
246 ret.z = (transform.m02 * vec.x) + (transform.m12 * vec.y) + (transform.m22 * vec.z);
250inline ogt_mesh_transform _make_transform(
251 float f00,
float f01,
float f02,
float f03,
252 float f10,
float f11,
float f12,
float f13,
253 float f20,
float f21,
float f22,
float f23,
254 float f30,
float f31,
float f32,
float f33)
256 ogt_mesh_transform ret;
285static inline const ogt_mesh_vec3* _make_vec3_ptr(
const float* pXyz_elements)
292 return (a.x * b.x) + (a.y * b.y) + (a.z * b.z);
298 ret.x = (a.y * b.z) - (a.z * b.y);
299 ret.y = (a.z * b.x) - (a.x * b.z);
300 ret.z = (a.x * b.y) - (a.y * b.x);
322 float len = sqrtf(a.x * a.x + a.y * a.y + a.z * a.z);
324 float len_inv = 1.0f / len;
326 ret.x = a.x * len_inv;
327 ret.y = a.y * len_inv;
328 ret.z = a.z * len_inv;
341static inline ogt_mesh_vertex _mesh_make_vertex(
float fPos_x,
float fPos_y,
float fPos_z,
float fNormal_x,
float fNormal_y,
float fNormal_z,
ogt_mesh_rgba color)
343 return _mesh_make_vertex(_make_vec3(fPos_x, fPos_y, fPos_z), _make_vec3(fNormal_x, fNormal_y, fNormal_z), color);
347static uint32_t _count_voxel_sized_faces(
const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z)
349 const int32_t k_stride_x = 1;
350 const int32_t k_stride_y = size_x;
351 const int32_t k_stride_z = size_x * size_y;
352 const int32_t k_max_x = size_x - 1;
353 const int32_t k_max_y = size_y - 1;
354 const int32_t k_max_z = size_z - 1;
356 uint32_t face_count = 0;
358 const uint8_t* current_voxel = pVoxels;
359 for (uint32_t k = 0; k < size_z; k++)
361 for (uint32_t j = 0; j < size_y; j++)
363 for (uint32_t i = 0; i < size_x; i++, current_voxel++)
365 if (current_voxel[0] != 0)
368 face_count += ((i == 0) || (current_voxel[-k_stride_x] == 0)) ? 1 : 0;
369 face_count += ((i == k_max_x) || (current_voxel[k_stride_x] == 0)) ? 1 : 0;
370 face_count += ((j == 0) || (current_voxel[-k_stride_y] == 0)) ? 1 : 0;
371 face_count += ((j == k_max_y) || (current_voxel[k_stride_y] == 0)) ? 1 : 0;
372 face_count += ((k == 0) || (current_voxel[-k_stride_z] == 0)) ? 1 : 0;
373 face_count += ((k == k_max_z) || (current_voxel[k_stride_z] == 0)) ? 1 : 0;
383static uint32_t murmur_hash2_size4(uint32_t h,
const uint32_t* pData, uint32_t data_len)
385 assert(data_len % 4 == 0);
386 const uint32_t m = 0x5bd1e995;
387 while (data_len >= 4)
389 uint32_t k = pData[0];
391 k ^= k >> (signed)24;
403static uint32_t* hash_table_find_vertex(uint32_t* pTable, uint32_t table_index_mask,
const uint8_t* pVertex_data, uint32_t vertex_size, uint32_t vertex_index)
405 uint32_t* this_vertex = (uint32_t*)&pVertex_data[vertex_index * vertex_size];
406 uint32_t bucket_index = murmur_hash2_size4(0, this_vertex, vertex_size) & table_index_mask;
408 for (uint32_t probe_count = 0; probe_count <= table_index_mask; probe_count++)
410 uint32_t* existing_index = &pTable[bucket_index];
412 if (*existing_index == UINT32_MAX)
413 return existing_index;
415 uint32_t* existing_vertex = (uint32_t*)&pVertex_data[*existing_index * vertex_size];
416 if (memcmp(this_vertex, existing_vertex, vertex_size) == 0)
418 assert(*existing_index < vertex_index);
419 return existing_index;
422 bucket_index = (bucket_index + probe_count + 1) & table_index_mask;
431static uint32_t* hash_table_find_vertex_position(uint32_t* pTable, uint32_t table_index_mask,
const ogt_mesh_vertex* pVertex_data, uint32_t vertex_index)
434 uint32_t bucket_index = murmur_hash2_size4(0, (uint32_t*)&this_vertex->pos,
sizeof(this_vertex->pos)) & table_index_mask;
436 for (uint32_t probe_count = 0; probe_count <= table_index_mask; probe_count++)
438 uint32_t* existing_index = &pTable[bucket_index];
440 if (*existing_index == UINT32_MAX)
441 return existing_index;
443 const ogt_mesh_vertex* existing_vertex = &pVertex_data[*existing_index];
444 if (memcmp(&this_vertex->pos, &existing_vertex->pos,
sizeof(this_vertex->pos)) == 0)
446 assert(*existing_index < vertex_index);
447 return existing_index;
450 bucket_index = (bucket_index + probe_count + 1) & table_index_mask;
461 uint32_t* indices = pMesh->indices;
462 uint32_t index_count = pMesh->index_count;
463 uint8_t* vertices = (uint8_t*)pMesh->vertices;
464 uint32_t vertex_count = pMesh->vertex_count;
466 assert(indices && index_count && vertices && vertex_count && vertex_size);
469 uint32_t hash_table_size = 1;
470 while (hash_table_size < vertex_count)
471 hash_table_size *= 2;
472 uint32_t hash_table_mask = hash_table_size - 1;
473 uint32_t* hash_table = (uint32_t*)_voxel_meshify_malloc(pCtx,
sizeof(uint32_t) * hash_table_size);
474 memset(hash_table, -1, hash_table_size *
sizeof(uint32_t));
477 uint32_t* remap_indices = (uint32_t*)_voxel_meshify_malloc(pCtx,
sizeof(uint32_t) * vertex_count);
478 memset(remap_indices, -1, vertex_count *
sizeof(uint32_t));
479 uint32_t num_unique_vertices = 0;
480 for (uint32_t vertex_index = 0; vertex_index < vertex_count; vertex_index++)
482 uint32_t* hash_table_entry = hash_table_find_vertex(hash_table, hash_table_mask, vertices, vertex_size, vertex_index);
483 if (*hash_table_entry == UINT32_MAX)
486 *hash_table_entry = vertex_index;
488 remap_indices[vertex_index] = num_unique_vertices++;
493 assert(remap_indices[*hash_table_entry] != UINT32_MAX);
494 remap_indices[vertex_index] = remap_indices[*hash_table_entry];
499 for (uint32_t i = 0; i < vertex_count; i++)
501 uint32_t dst_index = remap_indices[i];
502 uint32_t src_index = i;
503 assert(dst_index <= src_index);
504 memcpy(&vertices[dst_index * vertex_size], &vertices[src_index * vertex_size], vertex_size);
507 for (uint32_t i = 0; i < index_count; i++)
509 indices[i] = remap_indices[indices[i]];
512 _voxel_meshify_free(pCtx, hash_table);
513 _voxel_meshify_free(pCtx, remap_indices);
515 assert(num_unique_vertices <= pMesh->vertex_count);
516 pMesh->vertex_count = num_unique_vertices;
523 uint32_t* remap_indices = (uint32_t*)_voxel_meshify_malloc(pCtx,
sizeof(uint32_t) * pMesh->vertex_count);
524 memset(remap_indices, -1, pMesh->vertex_count *
sizeof(uint32_t));
527 uint32_t hash_table_size = 1;
528 while (hash_table_size < pMesh->vertex_count)
529 hash_table_size *= 2;
530 uint32_t hash_table_mask = hash_table_size - 1;
531 uint32_t* hash_table = (uint32_t*)_voxel_meshify_malloc(pCtx,
sizeof(uint32_t) * hash_table_size);
532 memset(hash_table, -1, hash_table_size *
sizeof(uint32_t));
535 uint32_t num_unique_vertices = 0;
536 for (uint32_t vertex_index = 0; vertex_index < pMesh->vertex_count; vertex_index++)
538 uint32_t* hash_table_entry = hash_table_find_vertex_position(hash_table, hash_table_mask, pMesh->vertices, vertex_index);
539 if (*hash_table_entry == UINT32_MAX)
542 *hash_table_entry = vertex_index;
543 remap_indices[vertex_index] = num_unique_vertices++;
548 assert(remap_indices[*hash_table_entry] != UINT32_MAX);
549 remap_indices[vertex_index] = remap_indices[*hash_table_entry];
553 _voxel_meshify_free(pCtx, hash_table);
558 memset(remap_normals, 0,
sizeof(
ogt_mesh_vec3) * pMesh->vertex_count);
560 for (uint32_t i = 0; i < pMesh->index_count; i += 3)
562 uint32_t i0 = pMesh->indices[i + 0];
563 uint32_t i1 = pMesh->indices[i + 1];
564 uint32_t i2 = pMesh->indices[i + 2];
568 ogt_mesh_vec3 normal = _cross3(_sub3(v1.pos, v0.pos), _sub3(v2.pos, v0.pos));
570 uint32_t ri0 = remap_indices[i0];
571 uint32_t ri1 = remap_indices[i1];
572 uint32_t ri2 = remap_indices[i2];
573 remap_normals[ri0] = _add3(remap_normals[ri0], normal);
574 remap_normals[ri1] = _add3(remap_normals[ri1], normal);
575 remap_normals[ri2] = _add3(remap_normals[ri2], normal);
579 for (uint32_t vertex_index = 0; vertex_index < pMesh->vertex_count; vertex_index++)
581 ogt_mesh_vec3 accumulated_normal = remap_normals[remap_indices[vertex_index]];
582 if (_dot3(accumulated_normal, accumulated_normal) > 0.001f)
583 pMesh->vertices[vertex_index].normal = _normalize3(accumulated_normal);
586 _voxel_meshify_free(pCtx, remap_normals);
587 _voxel_meshify_free(pCtx, remap_indices);
590static void _streaming_add_to_mesh(uint32_t x, uint32_t y, uint32_t z,
const ogt_mesh_vertex* pVertices, uint32_t vertex_count,
const uint32_t* pIndices, uint32_t index_count,
void* pStream_func_data)
598 memcpy(&mesh->vertices[mesh->vertex_count], pVertices, vertex_count *
sizeof(
ogt_mesh_vertex));
599 memcpy(&mesh->indices[mesh->index_count], pIndices, index_count *
sizeof(uint32_t));
600 mesh->vertex_count += vertex_count;
601 mesh->index_count += index_count;
605uint32_t ogt_face_count_from_paletted_voxels_simple(
const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z)
607 return _count_voxel_sized_faces(pVoxels, size_x, size_y, size_z);
611ogt_mesh* ogt_mesh_from_paletted_voxels_simple(
613 const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z,
const ogt_mesh_rgba* pPalette)
615 uint32_t max_face_count = _count_voxel_sized_faces(pVoxels, size_x, size_y, size_z);
616 uint32_t max_vertex_count = max_face_count * 4;
617 uint32_t max_index_count = max_face_count * 6;
619 uint32_t mesh_size =
sizeof(
ogt_mesh) + (max_vertex_count *
sizeof(
ogt_mesh_vertex)) + (max_index_count *
sizeof(uint32_t));
625 mesh->indices = (uint32_t*)&mesh->vertices[max_vertex_count];
626 mesh->vertex_count = 0;
627 mesh->index_count = 0;
629 ogt_stream_from_paletted_voxels_simple(pVoxels, size_x, size_y, size_z, pPalette, _streaming_add_to_mesh, mesh);
631 assert(mesh->vertex_count == max_vertex_count);
632 assert(mesh->index_count == max_index_count);
637void ogt_stream_from_paletted_voxels_simple(
638 const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z,
const ogt_mesh_rgba* pPalette,
639 ogt_voxel_simple_stream_func stream_func,
void* pStream_func_data)
642 const int32_t k_stride_x = 1;
643 const int32_t k_stride_y = size_x;
644 const int32_t k_stride_z = size_x * size_y;
645 const int32_t k_max_x = size_x - 1;
646 const int32_t k_max_y = size_y - 1;
647 const int32_t k_max_z = size_z - 1;
649 const uint8_t* current_voxel = pVoxels;
651 uint32_t total_vertex_count = 0;
652 uint32_t total_index_count = 0;
653 for (uint32_t k = 0; k < size_z; k++)
655 const float min_z = (float)k;
656 const float max_z = min_z + 1.0f;
657 for (uint32_t j = 0; j < size_y; j++)
659 const float min_y = (float)j;
660 const float max_y = min_y + 1.0f;
661 for (uint32_t i = 0; i < size_x; i++, current_voxel++)
664 if (current_voxel[0] == 0)
670 const float min_x = (float)i;
671 const float max_x = min_x + 1.0f;
674 uint32_t neg_x = ((i == 0) || (current_voxel[-k_stride_x] == 0));
675 uint32_t pos_x = ((i == k_max_x) || (current_voxel[k_stride_x] == 0));
676 uint32_t neg_y = ((j == 0) || (current_voxel[-k_stride_y] == 0));
677 uint32_t pos_y = ((j == k_max_y) || (current_voxel[k_stride_y] == 0));
678 uint32_t neg_z = ((k == 0) || (current_voxel[-k_stride_z] == 0));
679 uint32_t pos_z = ((k == k_max_z) || (current_voxel[k_stride_z] == 0));
682 const uint32_t face_count_needed = (neg_x + pos_x + neg_y + pos_y + neg_z + pos_z);
683 if (!face_count_needed)
688 uint32_t local_index[36];
690 uint32_t* current_index = local_index;
695 current_vertex[0] = _mesh_make_vertex(min_x, min_y, min_z, -1.0f, 0.0f, 0.0f, color);
696 current_vertex[1] = _mesh_make_vertex(min_x, max_y, min_z, -1.0f, 0.0f, 0.0f, color);
697 current_vertex[2] = _mesh_make_vertex(min_x, max_y, max_z, -1.0f, 0.0f, 0.0f, color);
698 current_vertex[3] = _mesh_make_vertex(min_x, min_y, max_z, -1.0f, 0.0f, 0.0f, color);
699 current_index[0] = total_vertex_count + 2;
700 current_index[1] = total_vertex_count + 1;
701 current_index[2] = total_vertex_count + 0;
702 current_index[3] = total_vertex_count + 0;
703 current_index[4] = total_vertex_count + 3;
704 current_index[5] = total_vertex_count + 2;
705 total_vertex_count += 4;
706 total_index_count += 6;
714 current_vertex[0] = _mesh_make_vertex(max_x, min_y, min_z, 1.0f, 0.0f, 0.0f, color);
715 current_vertex[1] = _mesh_make_vertex(max_x, max_y, min_z, 1.0f, 0.0f, 0.0f, color);
716 current_vertex[2] = _mesh_make_vertex(max_x, max_y, max_z, 1.0f, 0.0f, 0.0f, color);
717 current_vertex[3] = _mesh_make_vertex(max_x, min_y, max_z, 1.0f, 0.0f, 0.0f, color);
718 current_index[0] = total_vertex_count + 0;
719 current_index[1] = total_vertex_count + 1;
720 current_index[2] = total_vertex_count + 2;
721 current_index[3] = total_vertex_count + 2;
722 current_index[4] = total_vertex_count + 3;
723 current_index[5] = total_vertex_count + 0;
724 total_vertex_count += 4;
725 total_index_count += 6;
733 current_vertex[0] = _mesh_make_vertex(min_x, min_y, min_z, 0.0f, -1.0f, 0.0f, color);
734 current_vertex[1] = _mesh_make_vertex(max_x, min_y, min_z, 0.0f, -1.0f, 0.0f, color);
735 current_vertex[2] = _mesh_make_vertex(max_x, min_y, max_z, 0.0f, -1.0f, 0.0f, color);
736 current_vertex[3] = _mesh_make_vertex(min_x, min_y, max_z, 0.0f, -1.0f, 0.0f, color);
737 current_index[0] = total_vertex_count + 0;
738 current_index[1] = total_vertex_count + 1;
739 current_index[2] = total_vertex_count + 2;
740 current_index[3] = total_vertex_count + 2;
741 current_index[4] = total_vertex_count + 3;
742 current_index[5] = total_vertex_count + 0;
743 total_vertex_count += 4;
744 total_index_count += 6;
751 current_vertex[0] = _mesh_make_vertex(min_x, max_y, min_z, 0.0f, 1.0f, 0.0f, color);
752 current_vertex[1] = _mesh_make_vertex(max_x, max_y, min_z, 0.0f, 1.0f, 0.0f, color);
753 current_vertex[2] = _mesh_make_vertex(max_x, max_y, max_z, 0.0f, 1.0f, 0.0f, color);
754 current_vertex[3] = _mesh_make_vertex(min_x, max_y, max_z, 0.0f, 1.0f, 0.0f, color);
755 current_index[0] = total_vertex_count + 2;
756 current_index[1] = total_vertex_count + 1;
757 current_index[2] = total_vertex_count + 0;
758 current_index[3] = total_vertex_count + 0;
759 current_index[4] = total_vertex_count + 3;
760 current_index[5] = total_vertex_count + 2;
761 total_vertex_count += 4;
762 total_index_count += 6;
769 current_vertex[0] = _mesh_make_vertex(min_x, min_y, min_z, 0.0f, 0.0f, -1.0f, color);
770 current_vertex[1] = _mesh_make_vertex(max_x, min_y, min_z, 0.0f, 0.0f, -1.0f, color);
771 current_vertex[2] = _mesh_make_vertex(max_x, max_y, min_z, 0.0f, 0.0f, -1.0f, color);
772 current_vertex[3] = _mesh_make_vertex(min_x, max_y, min_z, 0.0f, 0.0f, -1.0f, color);
773 current_index[0] = total_vertex_count + 2;
774 current_index[1] = total_vertex_count + 1;
775 current_index[2] = total_vertex_count + 0;
776 current_index[3] = total_vertex_count + 0;
777 current_index[4] = total_vertex_count + 3;
778 current_index[5] = total_vertex_count + 2;
779 total_vertex_count += 4;
780 total_index_count += 6;
787 current_vertex[0] = _mesh_make_vertex(min_x, min_y, max_z, 0.0f, 0.0f, 1.0f, color);
788 current_vertex[1] = _mesh_make_vertex(max_x, min_y, max_z, 0.0f, 0.0f, 1.0f, color);
789 current_vertex[2] = _mesh_make_vertex(max_x, max_y, max_z, 0.0f, 0.0f, 1.0f, color);
790 current_vertex[3] = _mesh_make_vertex(min_x, max_y, max_z, 0.0f, 0.0f, 1.0f, color);
791 current_index[0] = total_vertex_count + 0;
792 current_index[1] = total_vertex_count + 1;
793 current_index[2] = total_vertex_count + 2;
794 current_index[3] = total_vertex_count + 2;
795 current_index[4] = total_vertex_count + 3;
796 current_index[5] = total_vertex_count + 0;
797 total_vertex_count += 4;
798 total_index_count += 6;
804 stream_func(i, j, k, local_vertex, face_count_needed * 4, local_index, face_count_needed * 6, pStream_func_data);
817void _greedy_meshify_voxels_in_face_direction(
818 const uint8_t* pVoxels,
820 int32_t size_x, int32_t size_y, int32_t size_z,
821 int32_t k_stride_x, int32_t k_stride_y, int32_t k_stride_z,
822 const ogt_mesh_transform& transform,
827 uint32_t max_voxels_per_slice = size_x * size_y;
830 assert(max_voxels_per_slice <= 65536);
831 ogt_mesh_bitset_64k voxel_polygonized;
833 ogt_mesh_vec3 normal = _transform_vector(transform, _make_vec3(0.0f, 0.0f, 1.0f));
835# define VOXELDATA_INDEX(_x, _y, _z) ((_x) * k_stride_x) + ((_y) * k_stride_y) + ((_z) * k_stride_z)
836# define LOCALDATA_INDEX(_x, _y) ((_x) + ((_y) * size_x))
839 uint32_t base_index_start = out_pMesh->index_count;
841 uint32_t* index_data = &out_pMesh->indices[out_pMesh->index_count];
842 ogt_mesh_vertex* vertex_data = &out_pMesh->vertices[out_pMesh->vertex_count];
848 bool is_parity_flipped = _dot3(*fwd, _cross3(*side, *up)) < 0.0f;
850 for (int32_t k0 = 0; k0 < size_z; k0++)
856 voxel_polygonized.clear(max_voxels_per_slice);
859 bool is_last_k_slice = (k1 == size_z);
862 for (int32_t j0 = 0; j0 < size_y; j0++)
864 for (int32_t i0 = 0; i0 < size_x; i0++)
867 uint8_t color_index = pVoxels[VOXELDATA_INDEX(i0, j0, k0)];
870 if ((color_index == 0) ||
871 voxel_polygonized.is_set(LOCALDATA_INDEX(i0, j0)) ||
872 (!is_last_k_slice && pVoxels[VOXELDATA_INDEX(i0, j0, k1)] != 0))
879 for (i1 = i0 + 1; i1 < size_x; i1++)
882 if ((pVoxels[VOXELDATA_INDEX(i1, j0, k0)] != color_index) ||
883 (voxel_polygonized.is_set(LOCALDATA_INDEX(i1, j0))) ||
884 (!is_last_k_slice && pVoxels[VOXELDATA_INDEX(i1, j0, k1)] != 0))
893 for (j1 = j0 + 1; j1 < size_y; j1++)
896 for (int32_t a = i0; a < i1; a++)
899 if ((pVoxels[VOXELDATA_INDEX(a, j1, k0)] != color_index) ||
900 (voxel_polygonized.is_set(LOCALDATA_INDEX(a, j1))) ||
901 (!is_last_k_slice && pVoxels[VOXELDATA_INDEX(a, j1, k1)] != 0))
914 for (int32_t b = j0; b < j1; b++)
915 for (int32_t a = i0; a < i1; a++)
916 voxel_polygonized.set(LOCALDATA_INDEX(a, b));
919 float min_x = (float)i0;
920 float max_x = (float)i1;
921 float min_y = (float)j0;
922 float max_y = (float)j1;
923 float max_z = (float)k1;
929 vertex_data[0] = _mesh_make_vertex(_transform_point(transform, _make_vec3(min_x, min_y, max_z)), normal, color);
930 vertex_data[1] = _mesh_make_vertex(_transform_point(transform, _make_vec3(max_x, min_y, max_z)), normal, color);
931 vertex_data[2] = _mesh_make_vertex(_transform_point(transform, _make_vec3(max_x, max_y, max_z)), normal, color);
932 vertex_data[3] = _mesh_make_vertex(_transform_point(transform, _make_vec3(min_x, max_y, max_z)), normal, color);
935 if (is_parity_flipped)
937 index_data[0] = out_pMesh->vertex_count + 0;
938 index_data[1] = out_pMesh->vertex_count + 3;
939 index_data[2] = out_pMesh->vertex_count + 2;
940 index_data[3] = out_pMesh->vertex_count + 2;
941 index_data[4] = out_pMesh->vertex_count + 1;
942 index_data[5] = out_pMesh->vertex_count + 0;
946 index_data[0] = out_pMesh->vertex_count + 0;
947 index_data[1] = out_pMesh->vertex_count + 1;
948 index_data[2] = out_pMesh->vertex_count + 2;
949 index_data[3] = out_pMesh->vertex_count + 2;
950 index_data[4] = out_pMesh->vertex_count + 3;
951 index_data[5] = out_pMesh->vertex_count + 0;
957 out_pMesh->vertex_count += 4;
958 out_pMesh->index_count += 6;
963# undef VOXELDATA_INDEX
964# undef LOCALDATA_INDEX
967ogt_mesh* ogt_mesh_from_paletted_voxels_greedy(
969 const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z,
const ogt_mesh_rgba* pPalette)
971 uint32_t max_face_count = _count_voxel_sized_faces(pVoxels, size_x, size_y, size_z);
972 uint32_t max_vertex_count = max_face_count * 4;
973 uint32_t max_index_count = max_face_count * 6;
975 uint32_t mesh_size =
sizeof(
ogt_mesh) + (max_vertex_count *
sizeof(
ogt_mesh_vertex)) + (max_index_count *
sizeof(uint32_t));
981 mesh->indices = (uint32_t*)&mesh->vertices[max_vertex_count];
982 mesh->vertex_count = 0;
983 mesh->index_count = 0;
985 const int32_t k_stride_x = 1;
986 const int32_t k_stride_y = size_x;
987 const int32_t k_stride_z = size_x * size_y;
991 ogt_mesh_transform transform_pos_y = _make_transform(
992 0.0f, 0.0f, 1.0f, 0.0f,
993 1.0f, 0.0f, 0.0f, 0.0f,
994 0.0f, 1.0f, 0.0f, 0.0f,
995 0.0f, 0.0f, 0.0f, 0.0f);
997 _greedy_meshify_voxels_in_face_direction(
999 size_z, size_x, size_y,
1000 k_stride_z, k_stride_x, k_stride_y,
1006 ogt_mesh_transform transform_neg_y = _make_transform(
1007 0.0f, 0.0f, 1.0f, 0.0f,
1008 1.0f, 0.0f, 0.0f, 0.0f,
1009 0.0f, -1.0f, 0.0f, 0.0f,
1010 0.0f, (
float)(size_y), 0.0f, 0.0f);
1012 _greedy_meshify_voxels_in_face_direction(
1013 pVoxels + (size_y - 1) * k_stride_y,
1015 size_z, size_x, size_y,
1016 k_stride_z, k_stride_x, -k_stride_y,
1022 ogt_mesh_transform transform_pos_x = _make_transform(
1023 0.0f, 1.0f, 0.0f, 0.0f,
1024 0.0f, 0.0f, 1.0f, 0.0f,
1025 1.0f, 0.0f, 0.0f, 0.0f,
1026 0.0f, 0.0f, 0.0f, 0.0f);
1028 _greedy_meshify_voxels_in_face_direction(
1030 size_y, size_z, size_x,
1031 k_stride_y, k_stride_z, k_stride_x,
1037 ogt_mesh_transform transform_neg_x = _make_transform(
1038 0.0f, 1.0f, 0.0f, 0.0f,
1039 0.0f, 0.0f, 1.0f, 0.0f,
1040 -1.0f, 0.0f, 0.0f, 0.0f,
1041 (
float)size_x, 0.0f, 0.0f, 0.0f);
1043 _greedy_meshify_voxels_in_face_direction(
1044 pVoxels + (size_x - 1) * k_stride_x,
1046 size_y, size_z, size_x,
1047 k_stride_y, k_stride_z, -k_stride_x,
1053 ogt_mesh_transform transform_pos_z = _make_transform(
1054 1.0f, 0.0f, 0.0f, 0.0f,
1055 0.0f, 1.0f, 0.0f, 0.0f,
1056 0.0f, 0.0f, 1.0f, 0.0f,
1057 0.0f, 0.0f, 0.0f, 0.0f);
1059 _greedy_meshify_voxels_in_face_direction(
1061 size_x, size_y, size_z,
1062 k_stride_x, k_stride_y, k_stride_z,
1068 ogt_mesh_transform transform_neg_z = _make_transform(
1069 1.0f, 0.0f, 0.0f, 0.0f,
1070 0.0f, 1.0f, 0.0f, 0.0f,
1071 0.0f, 0.0f, -1.0f, 0.0f,
1072 0.0f, 0.0f, (
float)size_z, 0.0f);
1074 _greedy_meshify_voxels_in_face_direction(
1075 pVoxels + (size_z - 1) * k_stride_z,
1077 size_x, size_y, size_z,
1078 k_stride_x, k_stride_y, -k_stride_z,
1083 assert(mesh->vertex_count <= max_vertex_count);
1084 assert(mesh->index_count <= max_index_count);
1088struct ogt_mesh_vec2i
1093inline ogt_mesh_vec2i make_vec2i(int32_t x, int32_t y)
1101inline ogt_mesh_vec2i operator+(
const ogt_mesh_vec2i& lhs,
const ogt_mesh_vec2i& rhs)
1104 ret.x = lhs.x + rhs.x;
1105 ret.y = lhs.y + rhs.y;
1109inline ogt_mesh_vec2i operator-(
const ogt_mesh_vec2i& lhs,
const ogt_mesh_vec2i& rhs)
1112 ret.x = lhs.x - rhs.x;
1113 ret.y = lhs.y - rhs.y;
1117inline ogt_mesh_vec2i operator*(
const ogt_mesh_vec2i& lhs,
const int32_t& rhs)
1120 ret.x = lhs.x * rhs;
1121 ret.y = lhs.y * rhs;
1125inline bool is_vec2i_equal(
const ogt_mesh_vec2i& lhs,
const ogt_mesh_vec2i& rhs)
1127 return lhs.x == rhs.x && lhs.y == rhs.y;
1130ogt_mesh_vec2i get_cardinal_unit_vector(
const ogt_mesh_vec2i& vec)
1132 assert((vec.x == 0 && vec.y != 0) || (vec.y == 0 && vec.x != 0));
1134 return make_vec2i(-1, 0);
1136 return make_vec2i(1, 0);
1138 return make_vec2i(0, -1);
1140 return make_vec2i(0, 1);
1142 return make_vec2i(0, 0);
1145int32_t get_cardinal_vector_length(
const ogt_mesh_vec2i& vec)
1147 assert((vec.x == 0 && vec.y != 0) || (vec.y == 0 && vec.x != 0));
1148 return vec.x == 0 ? abs(vec.y) : vec.y == 0 ? abs(vec.x) :
1153inline int32_t get_triangle_signed_area(
const ogt_mesh_vec2i& v0,
const ogt_mesh_vec2i& v1,
const ogt_mesh_vec2i& v2)
1155 return ((v0.x - v1.x) * (v2.y - v1.y)) - ((v0.y - v1.y) * (v2.x - v1.x));
1159inline bool is_triangle_convex(
const ogt_mesh_vec2i& v0,
const ogt_mesh_vec2i& v1,
const ogt_mesh_vec2i& v2)
1161 return get_triangle_signed_area(v0, v1, v2) > 0;
1165bool is_point_in_triangle(
const ogt_mesh_vec2i& v0,
const ogt_mesh_vec2i& v1,
const ogt_mesh_vec2i& v2,
const ogt_mesh_vec2i& p)
1167 bool convex_v0v1 = get_triangle_signed_area(v0, v1, p) >= 0;
1168 bool convex_v1v2 = get_triangle_signed_area(v1, v2, p) >= 0;
1169 bool convex_v2v0 = get_triangle_signed_area(v2, v0, p) >= 0;
1170 return (convex_v0v1 == convex_v1v2) && (convex_v0v1 == convex_v2v0);
1173uint32_t _tessellate_polygon(uint32_t* pIndices,
const ogt_mesh_vec2i* pVerts, uint32_t vert_count)
1175 static const uint32_t k_max_polygon_size = 16384;
1176 uint16_t ring_indices[k_max_polygon_size];
1177 assert(vert_count >= 3 && vert_count <= k_max_polygon_size);
1179 for (uint16_t i = 0; i < vert_count; i++)
1180 ring_indices[i] = i;
1181 uint32_t ring_count = vert_count;
1183 uint32_t index_count = 0;
1188 uint32_t no_progress_counter = 0;
1190 while (ring_count > 3)
1192 i0 = (i0 + 0) % ring_count;
1193 uint32_t i1 = (i0 + 1) % ring_count;
1194 uint32_t i2 = (i0 + 2) % ring_count;
1196 ogt_mesh_vec2i v0 = pVerts[ring_indices[i0]];
1197 ogt_mesh_vec2i v1 = pVerts[ring_indices[i1]];
1198 ogt_mesh_vec2i v2 = pVerts[ring_indices[i2]];
1201 bool can_triangulate = is_triangle_convex(v0, v1, v2);
1203 if (can_triangulate)
1206 for (uint32_t i = 0; i < ring_count; i++)
1208 if (i == i0 || i == i1 || i == i2)
1210 const ogt_mesh_vec2i& p = pVerts[ring_indices[i]];
1211 bool point_on_corner = is_vec2i_equal(v0, p) || is_vec2i_equal(v1, p) || is_vec2i_equal(v2, p);
1212 if (!point_on_corner && is_point_in_triangle(v0, v1, v2, pVerts[ring_indices[i]]))
1214 can_triangulate =
false;
1220 if (can_triangulate)
1222 pIndices[index_count++] = (uint32_t)ring_indices[i2];
1223 pIndices[index_count++] = (uint32_t)ring_indices[i1];
1224 pIndices[index_count++] = (uint32_t)ring_indices[i0];
1227 for (uint32_t i = i1; i < ring_count; i++)
1228 ring_indices[i] = ring_indices[i + 1];
1230 no_progress_counter = 0;
1234 no_progress_counter++;
1238 if (no_progress_counter == ring_count)
1244 pIndices[index_count++] = (uint32_t)ring_indices[2];
1245 pIndices[index_count++] = (uint32_t)ring_indices[1];
1246 pIndices[index_count++] = (uint32_t)ring_indices[0];
1252ogt_mesh_vec2i get_edge_bias(
const ogt_mesh_vec2i& edge_vert0,
const ogt_mesh_vec2i& edge_vert1)
1254 if (edge_vert0.x < edge_vert1.x)
1256 assert(edge_vert0.y == edge_vert1.y);
1257 return make_vec2i(0, 0);
1259 else if (edge_vert0.x > edge_vert1.x)
1261 assert(edge_vert0.y == edge_vert1.y);
1262 return make_vec2i(-1, -1);
1264 else if (edge_vert0.y < edge_vert1.y)
1266 assert(edge_vert0.x == edge_vert1.x);
1267 return make_vec2i(-1, 0);
1269 else if (edge_vert0.y > edge_vert1.y)
1271 assert(edge_vert0.x == edge_vert1.x);
1272 return make_vec2i(0, -1);
1277 return make_vec2i(0, 0);
1281uint32_t _tessellate_edge(ogt_mesh_vec2i* pTess, uint32_t max_tess,
const ogt_mesh_vec2i& edge_vert0,
const ogt_mesh_vec2i& edge_vert1,
1282 const uint8_t* pSlice_colors, int32_t size_x, int32_t size_y)
1285 uint32_t num_tess = 0;
1286 int32_t edge_len = get_cardinal_vector_length(edge_vert1 - edge_vert0);
1287 ogt_mesh_vec2i edge_bias = get_edge_bias(edge_vert0, edge_vert1);
1288 ogt_mesh_vec2i edge_step = get_cardinal_unit_vector(edge_vert1 - edge_vert0);
1289 ogt_mesh_vec2i curr_pos = edge_vert0 + edge_bias;
1292 if (edge_vert0.x < edge_vert1.x)
1295 assert(curr_pos.y <= size_y);
1296 if (curr_pos.y == size_y)
1299 else if (edge_vert0.x > edge_vert1.x)
1302 assert(curr_pos.y >= -1);
1303 if (curr_pos.y == -1)
1306 else if (edge_vert0.y < edge_vert1.y)
1309 assert(curr_pos.x >= -1);
1310 if (curr_pos.x == -1)
1313 else if (edge_vert0.y > edge_vert1.y)
1316 assert(curr_pos.x <= size_x);
1317 if (curr_pos.x == size_x)
1326 uint8_t last_color_index = pSlice_colors[curr_pos.x + (curr_pos.y * size_x)];
1327 curr_pos = curr_pos + edge_step;
1329 for (int32_t i = 1; i < edge_len; i++)
1331 uint8_t curr_color_index = pSlice_colors[curr_pos.x + (curr_pos.y * size_x)];
1332 if (curr_color_index != last_color_index)
1334 assert(num_tess < max_tess);
1335 pTess[num_tess++] = curr_pos - edge_bias;
1336 last_color_index = curr_color_index;
1338 curr_pos = curr_pos + edge_step;
1423int32_t _construct_polygon_for_slice(ogt_mesh_vec2i* pVerts, uint32_t max_verts, int32_t i, int32_t j, int32_t size_x, int32_t size_y,
const uint8_t* pSlice_colors, ogt_mesh_bitset_64k& ref_voxel_polygonized)
1425 assert(max_verts > 4);
1427 pVerts[0] = make_vec2i(i, j);
1428 pVerts[1] = make_vec2i(i, j + 1);
1429 pVerts[2] = make_vec2i(i + 1, j + 1);
1430 pVerts[3] = make_vec2i(i + 1, j);
1431 int32_t vert_count = 4;
1433 uint8_t polygon_color_index = pSlice_colors[i + (j * size_x)];
1436 ref_voxel_polygonized.set(i + (j * size_x));
1438 int32_t next_edge_index = 0;
1439 int32_t no_progress_counter = 0;
1440 while (no_progress_counter < vert_count)
1444 int32_t v0 = next_edge_index < 1 ? vert_count - 1 : next_edge_index - 1;
1445 int32_t v1 = next_edge_index;
1446 int32_t v2 = (v1 < (vert_count - 1)) ? v1 + 1 : 0;
1447 int32_t v3 = (v2 < (vert_count - 1)) ? v2 + 1 : 0;
1450 ogt_mesh_vec2i edge0_unitvec = get_cardinal_unit_vector(pVerts[v1] - pVerts[v0]);
1451 ogt_mesh_vec2i edge1_unitvec = get_cardinal_unit_vector(pVerts[v2] - pVerts[v1]);
1452 ogt_mesh_vec2i edge2_unitvec = get_cardinal_unit_vector(pVerts[v3] - pVerts[v2]);
1453 ogt_mesh_vec2i edge1_normal = make_vec2i(-edge1_unitvec.y, edge1_unitvec.x);
1455 bool can_extrude_edge1 = !is_vec2i_equal(edge1_normal, (edge0_unitvec * -1)) && !is_vec2i_equal(edge1_normal, edge2_unitvec);
1457 int32_t edge1_pushed_distance = 0;
1458 if (can_extrude_edge1)
1460 int32_t edge1_len = get_cardinal_vector_length(pVerts[v2] - pVerts[v1]);
1462 ogt_mesh_vec2i edge1_origin = pVerts[v1] + get_edge_bias(pVerts[v1], pVerts[v2]);
1464 while (edge1_origin.x >= 0 && edge1_origin.y >= 0 && edge1_origin.x < size_x && edge1_origin.y < size_y)
1469 ogt_mesh_vec2i edge1_cursor = edge1_origin;
1470 bool can_push_edge =
true;
1471 for (int32_t idx = 0; idx < edge1_len; idx++)
1473 assert(edge1_cursor.x >= 0 && edge1_cursor.x < size_x && edge1_cursor.y >= 0 && edge1_cursor.y < size_y);
1474 int32_t slice_index = edge1_cursor.x + (edge1_cursor.y * size_x);
1475 if (pSlice_colors[slice_index] != polygon_color_index || ref_voxel_polygonized.is_set(slice_index))
1477 can_push_edge =
false;
1480 edge1_cursor = edge1_cursor + edge1_unitvec;
1487 ogt_mesh_vec2i edge1_cursor2 = edge1_origin;
1488 for (int32_t idx = 0; idx < edge1_len; idx++)
1490 int32_t slice_index = edge1_cursor2.x + (edge1_cursor2.y * size_x);
1491 ref_voxel_polygonized.set(slice_index);
1492 edge1_cursor2 = edge1_cursor2 + edge1_unitvec;
1497 edge1_pushed_distance++;
1498 edge1_origin = edge1_origin + edge1_normal;
1502 if (!edge1_pushed_distance)
1505 next_edge_index = (next_edge_index + 1) % vert_count;
1507 no_progress_counter++;
1515 ogt_mesh_vec2i cached_v0 = pVerts[v0];
1516 ogt_mesh_vec2i cached_v1 = pVerts[v1];
1517 ogt_mesh_vec2i cached_v2 = pVerts[v2];
1518 ogt_mesh_vec2i cached_v3 = pVerts[v3];
1519 ogt_mesh_vec2i extruded_v1 = pVerts[v1] + (edge1_normal * edge1_pushed_distance);
1520 ogt_mesh_vec2i extruded_v2 = pVerts[v2] + (edge1_normal * edge1_pushed_distance);
1524 bool is_e0e1_extrude = is_vec2i_equal(edge0_unitvec, edge1_unitvec);
1525 bool is_e1e2_extrude = is_vec2i_equal(edge1_unitvec, edge2_unitvec);
1528 const uint32_t k_max_tessellations = 512;
1529 assert(edge1_pushed_distance < k_max_tessellations);
1530 ogt_mesh_vec2i tess_buffer[k_max_tessellations];
1531 uint32_t tess_offset = 0;
1534 uint32_t e0_offset = tess_offset;
1535 if (is_e0e1_extrude)
1537 tess_buffer[tess_offset++] = cached_v0;
1538 tess_buffer[tess_offset++] = cached_v1;
1542 tess_buffer[tess_offset++] = cached_v0;
1543 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, cached_v0, extruded_v1, pSlice_colors, size_x, size_y);
1545 uint32_t tess_count_e0 = tess_offset - e0_offset;
1547 uint32_t e1_offset = tess_offset;
1548 if (is_e0e1_extrude)
1549 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, cached_v1, extruded_v1, pSlice_colors, size_x, size_y);
1550 tess_buffer[tess_offset++] = extruded_v1;
1551 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, extruded_v1, extruded_v2, pSlice_colors, size_x, size_y);
1552 tess_buffer[tess_offset++] = extruded_v2;
1553 if (is_e1e2_extrude)
1554 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, extruded_v2, cached_v2, pSlice_colors, size_x, size_y);
1555 uint32_t tess_count_e1 = tess_offset - e1_offset;
1557 uint32_t e2_offset = tess_offset;
1558 if (is_e1e2_extrude)
1559 tess_buffer[tess_offset++] = cached_v2;
1561 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, extruded_v2, cached_v3, pSlice_colors, size_x, size_y);
1562 uint32_t tess_count_e2 = tess_offset - e2_offset;
1564 uint32_t e3_offset = tess_offset;
1565 tess_buffer[tess_offset++] = cached_v3;
1566 uint32_t tess_count_e3 = tess_offset - e3_offset;
1568 const ogt_mesh_vec2i* new_tess_e0 = &tess_buffer[e0_offset];
1569 const ogt_mesh_vec2i* new_tess_e1 = &tess_buffer[e1_offset];
1570 const ogt_mesh_vec2i* new_tess_e2 = &tess_buffer[e2_offset];
1571 const ogt_mesh_vec2i* new_tess_e3 = &tess_buffer[e3_offset];
1575 int32_t other1_count = vert_count - 4;
1576 int32_t other2_count = 0;
1577 int32_t old_other1 = (v3 + 1) % vert_count;
1578 int32_t old_other2 = 0;
1579 int32_t new_other2 = -1;
1580 int32_t new_v0, new_v1, new_v2, new_v3, new_other1;
1585 assert(v1 == 0 && v0 == (vert_count - 1));
1587 new_v2 = new_v1 + tess_count_e1;
1588 new_v3 = new_v2 + tess_count_e2;
1589 new_other1 = new_v3 + tess_count_e3;
1590 new_v0 = new_other1 + other1_count;
1595 assert(v2 == 0 && v1 == (vert_count - 1));
1597 new_v3 = new_v2 + tess_count_e2;
1598 new_other1 = new_v3 + tess_count_e3;
1599 new_v0 = new_other1 + other1_count;
1600 new_v1 = new_v0 + tess_count_e0;
1605 assert(v3 == 0 && v2 == (vert_count - 1));
1607 new_other1 = new_v3 + tess_count_e3;
1608 new_v0 = new_other1 + other1_count;
1609 new_v1 = new_v0 + tess_count_e0;
1610 new_v2 = new_v1 + tess_count_e1;
1615 other2_count = vert_count - v3 - 1;
1616 old_other2 = v3 + 1;
1617 other1_count = vert_count - 4 - other2_count;
1620 new_v0 = new_other1 + other1_count;
1621 new_v1 = new_v0 + tess_count_e0;
1622 new_v2 = new_v1 + tess_count_e1;
1623 new_v3 = new_v2 + tess_count_e2;
1624 new_other2 = new_v3 + tess_count_e3;
1626 uint32_t new_vert_count = vert_count - 4 + tess_count_e0 + tess_count_e1 + tess_count_e2 + tess_count_e3;
1628 assert(new_vert_count <= max_verts);
1630 if (old_other2 != new_other2 && other2_count)
1631 memmove(&pVerts[new_other2], &pVerts[old_other2], other2_count *
sizeof(ogt_mesh_vec2i));
1632 if (old_other1 != new_other1 && other1_count)
1633 memmove(&pVerts[new_other1], &pVerts[old_other1], other1_count *
sizeof(ogt_mesh_vec2i));
1635 memcpy(&pVerts[new_v0], new_tess_e0, tess_count_e0 *
sizeof(ogt_mesh_vec2i));
1637 memcpy(&pVerts[new_v1], new_tess_e1, tess_count_e1 *
sizeof(ogt_mesh_vec2i));
1639 memcpy(&pVerts[new_v2], new_tess_e2, tess_count_e2 *
sizeof(ogt_mesh_vec2i));
1641 memcpy(&pVerts[new_v3], new_tess_e3, tess_count_e3 *
sizeof(ogt_mesh_vec2i));
1643 vert_count = new_vert_count;
1646 next_edge_index = new_v1;
1649 no_progress_counter = 0;
1655void _polygon_meshify_voxels_in_face_direction(
1656 const uint8_t* pVoxels,
1658 int32_t size_x, int32_t size_y, int32_t size_z,
1659 int32_t k_stride_x, int32_t k_stride_y, int32_t k_stride_z,
1660 const ogt_mesh_transform& transform,
1664 uint32_t max_voxels_per_slice = size_x * size_y;
1665 assert(max_voxels_per_slice <= 65536);
1666 ogt_mesh_bitset_64k voxel_polygonized;
1667 uint8_t slice_colors[65536];
1673 bool is_parity_flipped = _dot3(*fwd, _cross3(*side, *up)) < 0.0f;
1675 ogt_mesh_vec3 normal = _transform_vector(transform, _make_vec3(0.0f, 0.0f, 1.0f));
1677 for (int32_t k = 0; k < (int32_t)size_z; k++)
1679 bool is_last_slice = (k == (size_z - 1)) ?
true : false;
1682 voxel_polygonized.clear(max_voxels_per_slice);
1686 uint32_t num_non_empty_cells = 0;
1687 for (int32_t j = 0; j < size_y; j++)
1689 for (int32_t i = 0; i < size_x; i++)
1691 int32_t index_in_slice = i + (j * size_x);
1692 uint8_t cell_color = pVoxels[i * k_stride_x + j * k_stride_y + (k + 0) * k_stride_z];
1699 uint8_t next_cell_color = !is_last_slice ? pVoxels[i * k_stride_x + j * k_stride_y + (k + 1) * k_stride_z] : 0;
1700 if (next_cell_color != 0)
1702 cell_color = next_cell_color;
1703 voxel_polygonized.set(index_in_slice);
1705 slice_colors[index_in_slice] = cell_color;
1707 num_non_empty_cells += (cell_color != 0) ? 1 : 0;
1711 if (!num_non_empty_cells)
1715 for (int32_t j = 0; j < (int32_t)size_y; j++)
1717 for (int32_t i = 0; i < (int32_t)size_x; i++)
1719 int32_t index_in_slice = i + j * size_x;
1722 uint8_t color_index = slice_colors[index_in_slice];
1723 if (color_index == 0)
1727 if (voxel_polygonized.is_set(index_in_slice))
1737 const uint32_t MAX_VERTS = 4096;
1738 ogt_mesh_vec2i verts[MAX_VERTS];
1739 uint32_t vert_count = _construct_polygon_for_slice(verts, MAX_VERTS, i, j, size_x, size_y, slice_colors, voxel_polygonized);
1744 uint32_t base_vertex_index = pMesh->vertex_count;
1745 for (uint32_t idx = 0; idx < vert_count; idx++)
1747 pMesh->vertices[pMesh->vertex_count++] = _mesh_make_vertex(_transform_point(transform, _make_vec3((
float)verts[idx].x, (
float)verts[idx].y, (
float)(k + 1))), normal, color);
1751 uint32_t tessellated_index_count = _tessellate_polygon(&pMesh->indices[pMesh->index_count], verts, vert_count);
1754 if (is_parity_flipped)
1756 for (uint32_t idx = 0; idx < tessellated_index_count; idx += 3)
1758 uint32_t i0 = pMesh->indices[pMesh->index_count + idx + 0];
1759 uint32_t i1 = pMesh->indices[pMesh->index_count + idx + 1];
1760 uint32_t i2 = pMesh->indices[pMesh->index_count + idx + 2];
1761 pMesh->indices[pMesh->index_count + idx + 0] = base_vertex_index + i2;
1762 pMesh->indices[pMesh->index_count + idx + 1] = base_vertex_index + i1;
1763 pMesh->indices[pMesh->index_count + idx + 2] = base_vertex_index + i0;
1768 for (uint32_t idx = 0; idx < tessellated_index_count; idx += 3)
1770 uint32_t i0 = pMesh->indices[pMesh->index_count + idx + 0];
1771 uint32_t i1 = pMesh->indices[pMesh->index_count + idx + 1];
1772 uint32_t i2 = pMesh->indices[pMesh->index_count + idx + 2];
1773 pMesh->indices[pMesh->index_count + idx + 0] = base_vertex_index + i0;
1774 pMesh->indices[pMesh->index_count + idx + 1] = base_vertex_index + i1;
1775 pMesh->indices[pMesh->index_count + idx + 2] = base_vertex_index + i2;
1779 pMesh->index_count += tessellated_index_count;
1794ogt_mesh* ogt_mesh_from_paletted_voxels_polygon(
1796 const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z,
const ogt_mesh_rgba* pPalette)
1798 uint32_t max_face_count = _count_voxel_sized_faces(pVoxels, size_x, size_y, size_z);
1799 uint32_t max_vertex_count = max_face_count * 4;
1800 uint32_t max_index_count = max_face_count * 6;
1802 uint32_t mesh_size =
sizeof(
ogt_mesh) + (max_vertex_count *
sizeof(
ogt_mesh_vertex)) + (max_index_count *
sizeof(uint32_t));
1808 mesh->indices = (uint32_t*)&mesh->vertices[max_vertex_count];
1809 mesh->vertex_count = 0;
1810 mesh->index_count = 0;
1812 const int32_t k_stride_x = 1;
1813 const int32_t k_stride_y = size_x;
1814 const int32_t k_stride_z = size_x * size_y;
1818 ogt_mesh_transform transform_pos_y = _make_transform(
1819 0.0f, 0.0f, 1.0f, 0.0f,
1820 1.0f, 0.0f, 0.0f, 0.0f,
1821 0.0f, 1.0f, 0.0f, 0.0f,
1822 0.0f, 0.0f, 0.0f, 0.0f);
1824 _polygon_meshify_voxels_in_face_direction(
1826 size_z, size_x, size_y,
1827 k_stride_z, k_stride_x, k_stride_y,
1834 ogt_mesh_transform transform_neg_y = _make_transform(
1835 0.0f, 0.0f, 1.0f, 0.0f,
1836 1.0f, 0.0f, 0.0f, 0.0f,
1837 0.0f, -1.0f, 0.0f, 0.0f,
1838 0.0f, (
float)(size_y), 0.0f, 0.0f);
1840 _polygon_meshify_voxels_in_face_direction(
1841 pVoxels + (size_y - 1) * k_stride_y,
1843 size_z, size_x, size_y,
1844 k_stride_z, k_stride_x, -k_stride_y,
1850 ogt_mesh_transform transform_pos_x = _make_transform(
1851 0.0f, 1.0f, 0.0f, 0.0f,
1852 0.0f, 0.0f, 1.0f, 0.0f,
1853 1.0f, 0.0f, 0.0f, 0.0f,
1854 0.0f, 0.0f, 0.0f, 0.0f);
1856 _polygon_meshify_voxels_in_face_direction(
1858 size_y, size_z, size_x,
1859 k_stride_y, k_stride_z, k_stride_x,
1865 ogt_mesh_transform transform_neg_x = _make_transform(
1866 0.0f, 1.0f, 0.0f, 0.0f,
1867 0.0f, 0.0f, 1.0f, 0.0f,
1868 -1.0f, 0.0f, 0.0f, 0.0f,
1869 (
float)size_x, 0.0f, 0.0f, 0.0f);
1871 _polygon_meshify_voxels_in_face_direction(
1872 pVoxels + (size_x - 1) * k_stride_x,
1874 size_y, size_z, size_x,
1875 k_stride_y, k_stride_z, -k_stride_x,
1881 ogt_mesh_transform transform_pos_z = _make_transform(
1882 1.0f, 0.0f, 0.0f, 0.0f,
1883 0.0f, 1.0f, 0.0f, 0.0f,
1884 0.0f, 0.0f, 1.0f, 0.0f,
1885 0.0f, 0.0f, 0.0f, 0.0f);
1887 _polygon_meshify_voxels_in_face_direction(
1889 size_x, size_y, size_z,
1890 k_stride_x, k_stride_y, k_stride_z,
1896 ogt_mesh_transform transform_neg_z = _make_transform(
1897 1.0f, 0.0f, 0.0f, 0.0f,
1898 0.0f, 1.0f, 0.0f, 0.0f,
1899 0.0f, 0.0f, -1.0f, 0.0f,
1900 0.0f, 0.0f, (
float)size_z, 0.0f);
1902 _polygon_meshify_voxels_in_face_direction(
1903 pVoxels + (size_z - 1) * k_stride_z,
1905 size_x, size_y, size_z,
1906 k_stride_x, k_stride_y, -k_stride_z,
1911 assert(mesh->vertex_count <= max_vertex_count);
1912 assert(mesh->index_count <= max_index_count);
1920 _voxel_meshify_free(pCtx, pMesh);
Definition ogt_voxel_meshify.h:107
Definition ogt_voxel_meshify.h:101
Definition ogt_voxel_meshify.h:113
Definition ogt_voxel_meshify.h:121
Definition ogt_voxel_meshify.h:139