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) : 0;
1152inline int32_t get_triangle_signed_area(
const ogt_mesh_vec2i& v0,
const ogt_mesh_vec2i& v1,
const ogt_mesh_vec2i& v2)
1154 return ((v0.x - v1.x) * (v2.y - v1.y)) - ((v0.y - v1.y) * (v2.x - v1.x));
1158inline bool is_triangle_convex(
const ogt_mesh_vec2i& v0,
const ogt_mesh_vec2i& v1,
const ogt_mesh_vec2i& v2)
1160 return get_triangle_signed_area(v0, v1, v2) > 0;
1164bool is_point_in_triangle(
const ogt_mesh_vec2i& v0,
const ogt_mesh_vec2i& v1,
const ogt_mesh_vec2i& v2,
const ogt_mesh_vec2i& p)
1166 bool convex_v0v1 = get_triangle_signed_area(v0, v1, p) >= 0;
1167 bool convex_v1v2 = get_triangle_signed_area(v1, v2, p) >= 0;
1168 bool convex_v2v0 = get_triangle_signed_area(v2, v0, p) >= 0;
1169 return (convex_v0v1 == convex_v1v2) && (convex_v0v1 == convex_v2v0);
1172uint32_t _tessellate_polygon(uint32_t* pIndices,
const ogt_mesh_vec2i* pVerts, uint32_t vert_count)
1174 static const uint32_t k_max_polygon_size = 16384;
1175 uint16_t ring_indices[k_max_polygon_size];
1176 assert(vert_count >= 3 && vert_count <= k_max_polygon_size);
1178 for (uint16_t i = 0; i < vert_count; i++)
1179 ring_indices[i] = i;
1180 uint32_t ring_count = vert_count;
1182 uint32_t index_count = 0;
1187 uint32_t no_progress_counter = 0;
1189 while (ring_count > 3)
1191 i0 = (i0 + 0) % ring_count;
1192 uint32_t i1 = (i0 + 1) % ring_count;
1193 uint32_t i2 = (i0 + 2) % ring_count;
1195 ogt_mesh_vec2i v0 = pVerts[ring_indices[i0]];
1196 ogt_mesh_vec2i v1 = pVerts[ring_indices[i1]];
1197 ogt_mesh_vec2i v2 = pVerts[ring_indices[i2]];
1200 bool can_triangulate = is_triangle_convex(v0, v1, v2);
1202 if (can_triangulate)
1205 for (uint32_t i = 0; i < ring_count; i++)
1207 if (i == i0 || i == i1 || i == i2)
1209 const ogt_mesh_vec2i& p = pVerts[ring_indices[i]];
1210 bool point_on_corner = is_vec2i_equal(v0, p) || is_vec2i_equal(v1, p) || is_vec2i_equal(v2, p);
1211 if (!point_on_corner && is_point_in_triangle(v0, v1, v2, pVerts[ring_indices[i]]))
1213 can_triangulate =
false;
1219 if (can_triangulate)
1221 pIndices[index_count++] = (uint32_t)ring_indices[i2];
1222 pIndices[index_count++] = (uint32_t)ring_indices[i1];
1223 pIndices[index_count++] = (uint32_t)ring_indices[i0];
1226 for (uint32_t i = i1; i < ring_count; i++)
1227 ring_indices[i] = ring_indices[i + 1];
1229 no_progress_counter = 0;
1233 no_progress_counter++;
1237 if (no_progress_counter == ring_count)
1243 pIndices[index_count++] = (uint32_t)ring_indices[2];
1244 pIndices[index_count++] = (uint32_t)ring_indices[1];
1245 pIndices[index_count++] = (uint32_t)ring_indices[0];
1251ogt_mesh_vec2i get_edge_bias(
const ogt_mesh_vec2i& edge_vert0,
const ogt_mesh_vec2i& edge_vert1)
1253 if (edge_vert0.x < edge_vert1.x)
1255 assert(edge_vert0.y == edge_vert1.y);
1256 return make_vec2i(0, 0);
1258 else if (edge_vert0.x > edge_vert1.x)
1260 assert(edge_vert0.y == edge_vert1.y);
1261 return make_vec2i(-1, -1);
1263 else if (edge_vert0.y < edge_vert1.y)
1265 assert(edge_vert0.x == edge_vert1.x);
1266 return make_vec2i(-1, 0);
1268 else if (edge_vert0.y > edge_vert1.y)
1270 assert(edge_vert0.x == edge_vert1.x);
1271 return make_vec2i(0, -1);
1276 return make_vec2i(0, 0);
1280uint32_t _tessellate_edge(ogt_mesh_vec2i* pTess, uint32_t max_tess,
const ogt_mesh_vec2i& edge_vert0,
const ogt_mesh_vec2i& edge_vert1,
1281 const uint8_t* pSlice_colors, int32_t size_x, int32_t size_y)
1284 uint32_t num_tess = 0;
1285 int32_t edge_len = get_cardinal_vector_length(edge_vert1 - edge_vert0);
1286 ogt_mesh_vec2i edge_bias = get_edge_bias(edge_vert0, edge_vert1);
1287 ogt_mesh_vec2i edge_step = get_cardinal_unit_vector(edge_vert1 - edge_vert0);
1288 ogt_mesh_vec2i curr_pos = edge_vert0 + edge_bias;
1291 if (edge_vert0.x < edge_vert1.x)
1294 assert(curr_pos.y <= size_y);
1295 if (curr_pos.y == size_y)
1298 else if (edge_vert0.x > edge_vert1.x)
1301 assert(curr_pos.y >= -1);
1302 if (curr_pos.y == -1)
1305 else if (edge_vert0.y < edge_vert1.y)
1308 assert(curr_pos.x >= -1);
1309 if (curr_pos.x == -1)
1312 else if (edge_vert0.y > edge_vert1.y)
1315 assert(curr_pos.x <= size_x);
1316 if (curr_pos.x == size_x)
1325 uint8_t last_color_index = pSlice_colors[curr_pos.x + (curr_pos.y * size_x)];
1326 curr_pos = curr_pos + edge_step;
1328 for (int32_t i = 1; i < edge_len; i++)
1330 uint8_t curr_color_index = pSlice_colors[curr_pos.x + (curr_pos.y * size_x)];
1331 if (curr_color_index != last_color_index)
1333 assert(num_tess < max_tess);
1334 pTess[num_tess++] = curr_pos - edge_bias;
1335 last_color_index = curr_color_index;
1337 curr_pos = curr_pos + edge_step;
1422int32_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)
1424 assert(max_verts > 4);
1426 pVerts[0] = make_vec2i(i, j);
1427 pVerts[1] = make_vec2i(i, j + 1);
1428 pVerts[2] = make_vec2i(i + 1, j + 1);
1429 pVerts[3] = make_vec2i(i + 1, j);
1430 int32_t vert_count = 4;
1432 uint8_t polygon_color_index = pSlice_colors[i + (j * size_x)];
1435 ref_voxel_polygonized.set(i + (j * size_x));
1437 int32_t next_edge_index = 0;
1438 int32_t no_progress_counter = 0;
1439 while (no_progress_counter < vert_count)
1443 int32_t v0 = next_edge_index < 1 ? vert_count - 1 : next_edge_index - 1;
1444 int32_t v1 = next_edge_index;
1445 int32_t v2 = (v1 < (vert_count - 1)) ? v1 + 1 : 0;
1446 int32_t v3 = (v2 < (vert_count - 1)) ? v2 + 1 : 0;
1449 ogt_mesh_vec2i edge0_unitvec = get_cardinal_unit_vector(pVerts[v1] - pVerts[v0]);
1450 ogt_mesh_vec2i edge1_unitvec = get_cardinal_unit_vector(pVerts[v2] - pVerts[v1]);
1451 ogt_mesh_vec2i edge2_unitvec = get_cardinal_unit_vector(pVerts[v3] - pVerts[v2]);
1452 ogt_mesh_vec2i edge1_normal = make_vec2i(-edge1_unitvec.y, edge1_unitvec.x);
1454 bool can_extrude_edge1 = !is_vec2i_equal(edge1_normal, (edge0_unitvec * -1)) && !is_vec2i_equal(edge1_normal, edge2_unitvec);
1456 int32_t edge1_pushed_distance = 0;
1457 if (can_extrude_edge1)
1459 int32_t edge1_len = get_cardinal_vector_length(pVerts[v2] - pVerts[v1]);
1461 ogt_mesh_vec2i edge1_origin = pVerts[v1] + get_edge_bias(pVerts[v1], pVerts[v2]);
1463 while (edge1_origin.x >= 0 && edge1_origin.y >= 0 && edge1_origin.x < size_x && edge1_origin.y < size_y)
1468 ogt_mesh_vec2i edge1_cursor = edge1_origin;
1469 bool can_push_edge =
true;
1470 for (int32_t idx = 0; idx < edge1_len; idx++)
1472 assert(edge1_cursor.x >= 0 && edge1_cursor.x < size_x && edge1_cursor.y >= 0 && edge1_cursor.y < size_y);
1473 int32_t slice_index = edge1_cursor.x + (edge1_cursor.y * size_x);
1474 if (pSlice_colors[slice_index] != polygon_color_index || ref_voxel_polygonized.is_set(slice_index))
1476 can_push_edge =
false;
1479 edge1_cursor = edge1_cursor + edge1_unitvec;
1486 ogt_mesh_vec2i edge1_cursor2 = edge1_origin;
1487 for (int32_t idx = 0; idx < edge1_len; idx++)
1489 int32_t slice_index = edge1_cursor2.x + (edge1_cursor2.y * size_x);
1490 ref_voxel_polygonized.set(slice_index);
1491 edge1_cursor2 = edge1_cursor2 + edge1_unitvec;
1496 edge1_pushed_distance++;
1497 edge1_origin = edge1_origin + edge1_normal;
1501 if (!edge1_pushed_distance)
1504 next_edge_index = (next_edge_index + 1) % vert_count;
1506 no_progress_counter++;
1514 ogt_mesh_vec2i cached_v0 = pVerts[v0];
1515 ogt_mesh_vec2i cached_v1 = pVerts[v1];
1516 ogt_mesh_vec2i cached_v2 = pVerts[v2];
1517 ogt_mesh_vec2i cached_v3 = pVerts[v3];
1518 ogt_mesh_vec2i extruded_v1 = pVerts[v1] + (edge1_normal * edge1_pushed_distance);
1519 ogt_mesh_vec2i extruded_v2 = pVerts[v2] + (edge1_normal * edge1_pushed_distance);
1523 bool is_e0e1_extrude = is_vec2i_equal(edge0_unitvec, edge1_unitvec);
1524 bool is_e1e2_extrude = is_vec2i_equal(edge1_unitvec, edge2_unitvec);
1527 const uint32_t k_max_tessellations = 512;
1528 assert(edge1_pushed_distance < k_max_tessellations);
1529 ogt_mesh_vec2i tess_buffer[k_max_tessellations];
1530 uint32_t tess_offset = 0;
1533 uint32_t e0_offset = tess_offset;
1534 if (is_e0e1_extrude)
1536 tess_buffer[tess_offset++] = cached_v0;
1537 tess_buffer[tess_offset++] = cached_v1;
1541 tess_buffer[tess_offset++] = cached_v0;
1542 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, cached_v0, extruded_v1, pSlice_colors, size_x, size_y);
1544 uint32_t tess_count_e0 = tess_offset - e0_offset;
1546 uint32_t e1_offset = tess_offset;
1547 if (is_e0e1_extrude)
1548 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, cached_v1, extruded_v1, pSlice_colors, size_x, size_y);
1549 tess_buffer[tess_offset++] = extruded_v1;
1550 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, extruded_v1, extruded_v2, pSlice_colors, size_x, size_y);
1551 tess_buffer[tess_offset++] = extruded_v2;
1552 if (is_e1e2_extrude)
1553 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, extruded_v2, cached_v2, pSlice_colors, size_x, size_y);
1554 uint32_t tess_count_e1 = tess_offset - e1_offset;
1556 uint32_t e2_offset = tess_offset;
1557 if (is_e1e2_extrude)
1558 tess_buffer[tess_offset++] = cached_v2;
1560 tess_offset += _tessellate_edge(&tess_buffer[tess_offset], k_max_tessellations - tess_offset, extruded_v2, cached_v3, pSlice_colors, size_x, size_y);
1561 uint32_t tess_count_e2 = tess_offset - e2_offset;
1563 uint32_t e3_offset = tess_offset;
1564 tess_buffer[tess_offset++] = cached_v3;
1565 uint32_t tess_count_e3 = tess_offset - e3_offset;
1567 const ogt_mesh_vec2i* new_tess_e0 = &tess_buffer[e0_offset];
1568 const ogt_mesh_vec2i* new_tess_e1 = &tess_buffer[e1_offset];
1569 const ogt_mesh_vec2i* new_tess_e2 = &tess_buffer[e2_offset];
1570 const ogt_mesh_vec2i* new_tess_e3 = &tess_buffer[e3_offset];
1574 int32_t other1_count = vert_count - 4;
1575 int32_t other2_count = 0;
1576 int32_t old_other1 = (v3 + 1) % vert_count;
1577 int32_t old_other2 = 0;
1578 int32_t new_other2 = -1;
1579 int32_t new_v0, new_v1, new_v2, new_v3, new_other1;
1584 assert(v1 == 0 && v0 == (vert_count - 1));
1586 new_v2 = new_v1 + tess_count_e1;
1587 new_v3 = new_v2 + tess_count_e2;
1588 new_other1 = new_v3 + tess_count_e3;
1589 new_v0 = new_other1 + other1_count;
1594 assert(v2 == 0 && v1 == (vert_count - 1));
1596 new_v3 = new_v2 + tess_count_e2;
1597 new_other1 = new_v3 + tess_count_e3;
1598 new_v0 = new_other1 + other1_count;
1599 new_v1 = new_v0 + tess_count_e0;
1604 assert(v3 == 0 && v2 == (vert_count - 1));
1606 new_other1 = new_v3 + tess_count_e3;
1607 new_v0 = new_other1 + other1_count;
1608 new_v1 = new_v0 + tess_count_e0;
1609 new_v2 = new_v1 + tess_count_e1;
1614 other2_count = vert_count - v3 - 1;
1615 old_other2 = v3 + 1;
1616 other1_count = vert_count - 4 - other2_count;
1619 new_v0 = new_other1 + other1_count;
1620 new_v1 = new_v0 + tess_count_e0;
1621 new_v2 = new_v1 + tess_count_e1;
1622 new_v3 = new_v2 + tess_count_e2;
1623 new_other2 = new_v3 + tess_count_e3;
1625 uint32_t new_vert_count = vert_count - 4 + tess_count_e0 + tess_count_e1 + tess_count_e2 + tess_count_e3;
1627 assert(new_vert_count <= max_verts);
1629 if (old_other2 != new_other2 && other2_count)
1630 memmove(&pVerts[new_other2], &pVerts[old_other2], other2_count *
sizeof(ogt_mesh_vec2i));
1631 if (old_other1 != new_other1 && other1_count)
1632 memmove(&pVerts[new_other1], &pVerts[old_other1], other1_count *
sizeof(ogt_mesh_vec2i));
1634 memcpy(&pVerts[new_v0], new_tess_e0, tess_count_e0 *
sizeof(ogt_mesh_vec2i));
1636 memcpy(&pVerts[new_v1], new_tess_e1, tess_count_e1 *
sizeof(ogt_mesh_vec2i));
1638 memcpy(&pVerts[new_v2], new_tess_e2, tess_count_e2 *
sizeof(ogt_mesh_vec2i));
1640 memcpy(&pVerts[new_v3], new_tess_e3, tess_count_e3 *
sizeof(ogt_mesh_vec2i));
1642 vert_count = new_vert_count;
1645 next_edge_index = new_v1;
1648 no_progress_counter = 0;
1654void _polygon_meshify_voxels_in_face_direction(
1655 const uint8_t* pVoxels,
1657 int32_t size_x, int32_t size_y, int32_t size_z,
1658 int32_t k_stride_x, int32_t k_stride_y, int32_t k_stride_z,
1659 const ogt_mesh_transform& transform,
1663 uint32_t max_voxels_per_slice = size_x * size_y;
1664 assert(max_voxels_per_slice <= 65536);
1665 ogt_mesh_bitset_64k voxel_polygonized;
1666 uint8_t slice_colors[65536];
1672 bool is_parity_flipped = _dot3(*fwd, _cross3(*side, *up)) < 0.0f;
1674 ogt_mesh_vec3 normal = _transform_vector(transform, _make_vec3(0.0f, 0.0f, 1.0f));
1676 for (int32_t k = 0; k < (int32_t)size_z; k++)
1678 bool is_last_slice = (k == (size_z - 1)) ? true :
false;
1681 voxel_polygonized.clear(max_voxels_per_slice);
1685 uint32_t num_non_empty_cells = 0;
1686 for (int32_t j = 0; j < size_y; j++)
1688 for (int32_t i = 0; i < size_x; i++)
1690 int32_t index_in_slice = i + (j * size_x);
1691 uint8_t cell_color = pVoxels[i * k_stride_x + j * k_stride_y + (k + 0) * k_stride_z];
1698 uint8_t next_cell_color = !is_last_slice ? pVoxels[i * k_stride_x + j * k_stride_y + (k + 1) * k_stride_z] : 0;
1699 if (next_cell_color != 0)
1701 cell_color = next_cell_color;
1702 voxel_polygonized.set(index_in_slice);
1704 slice_colors[index_in_slice] = cell_color;
1706 num_non_empty_cells += (cell_color != 0) ? 1 : 0;
1710 if (!num_non_empty_cells)
1714 for (int32_t j = 0; j < (int32_t)size_y; j++)
1716 for (int32_t i = 0; i < (int32_t)size_x; i++)
1718 int32_t index_in_slice = i + j * size_x;
1721 uint8_t color_index = slice_colors[index_in_slice];
1722 if (color_index == 0)
1726 if (voxel_polygonized.is_set(index_in_slice))
1736 const uint32_t MAX_VERTS = 4096;
1737 ogt_mesh_vec2i verts[MAX_VERTS];
1738 uint32_t vert_count = _construct_polygon_for_slice(verts, MAX_VERTS, i, j, size_x, size_y, slice_colors, voxel_polygonized);
1743 uint32_t base_vertex_index = pMesh->vertex_count;
1744 for (uint32_t idx = 0; idx < vert_count; idx++)
1746 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);
1750 uint32_t tessellated_index_count = _tessellate_polygon(&pMesh->indices[pMesh->index_count], verts, vert_count);
1753 if (is_parity_flipped)
1755 for (uint32_t idx = 0; idx < tessellated_index_count; idx += 3)
1757 uint32_t i0 = pMesh->indices[pMesh->index_count + idx + 0];
1758 uint32_t i1 = pMesh->indices[pMesh->index_count + idx + 1];
1759 uint32_t i2 = pMesh->indices[pMesh->index_count + idx + 2];
1760 pMesh->indices[pMesh->index_count + idx + 0] = base_vertex_index + i2;
1761 pMesh->indices[pMesh->index_count + idx + 1] = base_vertex_index + i1;
1762 pMesh->indices[pMesh->index_count + idx + 2] = base_vertex_index + i0;
1767 for (uint32_t idx = 0; idx < tessellated_index_count; idx += 3)
1769 uint32_t i0 = pMesh->indices[pMesh->index_count + idx + 0];
1770 uint32_t i1 = pMesh->indices[pMesh->index_count + idx + 1];
1771 uint32_t i2 = pMesh->indices[pMesh->index_count + idx + 2];
1772 pMesh->indices[pMesh->index_count + idx + 0] = base_vertex_index + i0;
1773 pMesh->indices[pMesh->index_count + idx + 1] = base_vertex_index + i1;
1774 pMesh->indices[pMesh->index_count + idx + 2] = base_vertex_index + i2;
1778 pMesh->index_count += tessellated_index_count;
1793ogt_mesh* ogt_mesh_from_paletted_voxels_polygon(
1795 const uint8_t* pVoxels, uint32_t size_x, uint32_t size_y, uint32_t size_z,
const ogt_mesh_rgba* pPalette)
1797 uint32_t max_face_count = _count_voxel_sized_faces(pVoxels, size_x, size_y, size_z);
1798 uint32_t max_vertex_count = max_face_count * 4;
1799 uint32_t max_index_count = max_face_count * 6;
1801 uint32_t mesh_size =
sizeof(
ogt_mesh) + (max_vertex_count *
sizeof(
ogt_mesh_vertex)) + (max_index_count *
sizeof(uint32_t));
1807 mesh->indices = (uint32_t*)&mesh->vertices[max_vertex_count];
1808 mesh->vertex_count = 0;
1809 mesh->index_count = 0;
1811 const int32_t k_stride_x = 1;
1812 const int32_t k_stride_y = size_x;
1813 const int32_t k_stride_z = size_x * size_y;
1817 ogt_mesh_transform transform_pos_y = _make_transform(
1818 0.0f, 0.0f, 1.0f, 0.0f,
1819 1.0f, 0.0f, 0.0f, 0.0f,
1820 0.0f, 1.0f, 0.0f, 0.0f,
1821 0.0f, 0.0f, 0.0f, 0.0f);
1823 _polygon_meshify_voxels_in_face_direction(
1825 size_z, size_x, size_y,
1826 k_stride_z, k_stride_x, k_stride_y,
1833 ogt_mesh_transform transform_neg_y = _make_transform(
1834 0.0f, 0.0f, 1.0f, 0.0f,
1835 1.0f, 0.0f, 0.0f, 0.0f,
1836 0.0f, -1.0f, 0.0f, 0.0f,
1837 0.0f, (
float)(size_y), 0.0f, 0.0f);
1839 _polygon_meshify_voxels_in_face_direction(
1840 pVoxels + (size_y - 1) * k_stride_y,
1842 size_z, size_x, size_y,
1843 k_stride_z, k_stride_x, -k_stride_y,
1849 ogt_mesh_transform transform_pos_x = _make_transform(
1850 0.0f, 1.0f, 0.0f, 0.0f,
1851 0.0f, 0.0f, 1.0f, 0.0f,
1852 1.0f, 0.0f, 0.0f, 0.0f,
1853 0.0f, 0.0f, 0.0f, 0.0f);
1855 _polygon_meshify_voxels_in_face_direction(
1857 size_y, size_z, size_x,
1858 k_stride_y, k_stride_z, k_stride_x,
1864 ogt_mesh_transform transform_neg_x = _make_transform(
1865 0.0f, 1.0f, 0.0f, 0.0f,
1866 0.0f, 0.0f, 1.0f, 0.0f,
1867 -1.0f, 0.0f, 0.0f, 0.0f,
1868 (
float)size_x, 0.0f, 0.0f, 0.0f);
1870 _polygon_meshify_voxels_in_face_direction(
1871 pVoxels + (size_x - 1) * k_stride_x,
1873 size_y, size_z, size_x,
1874 k_stride_y, k_stride_z, -k_stride_x,
1880 ogt_mesh_transform transform_pos_z = _make_transform(
1881 1.0f, 0.0f, 0.0f, 0.0f,
1882 0.0f, 1.0f, 0.0f, 0.0f,
1883 0.0f, 0.0f, 1.0f, 0.0f,
1884 0.0f, 0.0f, 0.0f, 0.0f);
1886 _polygon_meshify_voxels_in_face_direction(
1888 size_x, size_y, size_z,
1889 k_stride_x, k_stride_y, k_stride_z,
1895 ogt_mesh_transform transform_neg_z = _make_transform(
1896 1.0f, 0.0f, 0.0f, 0.0f,
1897 0.0f, 1.0f, 0.0f, 0.0f,
1898 0.0f, 0.0f, -1.0f, 0.0f,
1899 0.0f, 0.0f, (
float)size_z, 0.0f);
1901 _polygon_meshify_voxels_in_face_direction(
1902 pVoxels + (size_z - 1) * k_stride_z,
1904 size_x, size_y, size_z,
1905 k_stride_x, k_stride_y, -k_stride_z,
1910 assert(mesh->vertex_count <= max_vertex_count);
1911 assert(mesh->index_count <= max_index_count);
1919 _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