@@ -300,7 +300,7 @@ MVX_API MVX_INLINE int mvx_triangle_box_overlap(
300300 float pmax = mvx_maxf (mvx_maxf (p0 , p1 ), p2 );
301301 float pmin = mvx_minf (mvx_minf (p0 , p1 ), p2 );
302302 float rad = boxhalf .y * f .z + boxhalf .z * f .y + SLOP ;
303-
303+
304304 if (pmax < - rad || pmin > rad )
305305 {
306306 return 0 ;
@@ -575,6 +575,220 @@ MVX_API MVX_INLINE int mvx_voxelize_mesh(
575575 return 1 ;
576576}
577577
578+ /* Get voxel value with boundary checks. */
579+ #define MVX_GET_VOXEL (voxels , x , y , z , gx , gy , gz ) \
580+ (((x) >= 0 && (x) < (gx) && \
581+ (y) >= 0 && (y) < (gy) && \
582+ (z) >= 0 && (z) < (gz)) \
583+ ? (voxels)[(x) + (y) * (gx) + (z) * (gx) * (gy)] \
584+ : 0)
585+
586+ MVX_API MVX_INLINE int mvx_convert_voxels_to_mesh (
587+ unsigned char * voxels ,
588+ int grid_x ,
589+ int grid_y ,
590+ int grid_z ,
591+ float voxel_size ,
592+ float * out_vertices ,
593+ unsigned long out_vertices_cap ,
594+ unsigned long * out_vert_count ,
595+ int * out_indices ,
596+ unsigned long out_indices_cap ,
597+ unsigned long * out_index_count )
598+ {
599+ long x , y , z ;
600+ unsigned long current_vert_idx = 0 ;
601+ unsigned long current_index_idx = 0 ;
602+ float half_voxel_size = voxel_size * 0.5f ;
603+
604+ /* A set of 4 vertices for each of the 6 faces.
605+ * The order of vertices is chosen to provide consistent winding. */
606+ float mvx_face_vertices [6 ][4 ][3 ] = {
607+ /* +Z face */
608+ {{-1.0f , -1.0f , 1.0f }, {1.0f , -1.0f , 1.0f }, {1.0f , 1.0f , 1.0f }, {-1.0f , 1.0f , 1.0f }},
609+ /* -Z face */
610+ {{-1.0f , -1.0f , -1.0f }, {-1.0f , 1.0f , -1.0f }, {1.0f , 1.0f , -1.0f }, {1.0f , -1.0f , -1.0f }},
611+ /* +Y face */
612+ {{-1.0f , 1.0f , -1.0f }, {-1.0f , 1.0f , 1.0f }, {1.0f , 1.0f , 1.0f }, {1.0f , 1.0f , -1.0f }},
613+ /* -Y face */
614+ {{-1.0f , -1.0f , -1.0f }, {1.0f , -1.0f , -1.0f }, {1.0f , -1.0f , 1.0f }, {-1.0f , -1.0f , 1.0f }},
615+ /* +X face */
616+ {{1.0f , -1.0f , -1.0f }, {1.0f , 1.0f , -1.0f }, {1.0f , 1.0f , 1.0f }, {1.0f , -1.0f , 1.0f }},
617+ /* -X face */
618+ {{-1.0f , -1.0f , -1.0f }, {-1.0f , -1.0f , 1.0f }, {-1.0f , 1.0f , 1.0f }, {-1.0f , 1.0f , -1.0f }}};
619+
620+ /* Indices for a quad (two triangles) from 4 vertices. */
621+ int mvx_face_indices [6 ] = {0 , 1 , 2 , 0 , 2 , 3 };
622+
623+ /* Check for invalid input pointers. */
624+ if (!voxels || !out_vertices || !out_indices || !out_vert_count || !out_index_count )
625+ {
626+ return 0 ;
627+ }
628+
629+ * out_vert_count = 0 ;
630+ * out_index_count = 0 ;
631+
632+ for (z = 0 ; z < grid_z ; ++ z )
633+ {
634+ for (y = 0 ; y < grid_y ; ++ y )
635+ {
636+ for (x = 0 ; x < grid_x ; ++ x )
637+ {
638+ long id = x + y * grid_x + z * grid_x * grid_y ;
639+
640+ if (voxels [id ] == 1 )
641+ {
642+ /* Check for an empty neighbor in each direction. */
643+
644+ /* +X neighbor */
645+ if (MVX_GET_VOXEL (voxels , x + 1 , y , z , grid_x , grid_y , grid_z ) == 0 )
646+ {
647+ int i ;
648+
649+ if (current_vert_idx + 12 > out_vertices_cap || current_index_idx + 6 > out_indices_cap )
650+ {
651+ return 0 ;
652+ }
653+
654+ for (i = 0 ; i < 4 ; ++ i )
655+ {
656+ out_vertices [current_vert_idx ++ ] = (float )x * voxel_size + half_voxel_size + mvx_face_vertices [4 ][i ][0 ] * half_voxel_size ;
657+ out_vertices [current_vert_idx ++ ] = (float )y * voxel_size + half_voxel_size + mvx_face_vertices [4 ][i ][1 ] * half_voxel_size ;
658+ out_vertices [current_vert_idx ++ ] = (float )z * voxel_size + half_voxel_size + mvx_face_vertices [4 ][i ][2 ] * half_voxel_size ;
659+ }
660+
661+ for (i = 0 ; i < 6 ; ++ i )
662+ {
663+ out_indices [current_index_idx ++ ] = (int )((current_vert_idx / 3 ) - 4 ) + mvx_face_indices [i ];
664+ }
665+ }
666+
667+ /* -X neighbor */
668+ if (MVX_GET_VOXEL (voxels , x - 1 , y , z , grid_x , grid_y , grid_z ) == 0 )
669+ {
670+ int i ;
671+
672+ if (current_vert_idx + 12 > out_vertices_cap || current_index_idx + 6 > out_indices_cap )
673+ {
674+ return 0 ;
675+ }
676+
677+ for (i = 0 ; i < 4 ; ++ i )
678+ {
679+ out_vertices [current_vert_idx ++ ] = (float )x * voxel_size + half_voxel_size + mvx_face_vertices [5 ][i ][0 ] * half_voxel_size ;
680+ out_vertices [current_vert_idx ++ ] = (float )y * voxel_size + half_voxel_size + mvx_face_vertices [5 ][i ][1 ] * half_voxel_size ;
681+ out_vertices [current_vert_idx ++ ] = (float )z * voxel_size + half_voxel_size + mvx_face_vertices [5 ][i ][2 ] * half_voxel_size ;
682+ }
683+
684+ for (i = 0 ; i < 6 ; ++ i )
685+ {
686+ out_indices [current_index_idx ++ ] = (int )((current_vert_idx / 3 ) - 4 ) + mvx_face_indices [i ];
687+ }
688+ }
689+
690+ /* +Y neighbor */
691+ if (MVX_GET_VOXEL (voxels , x , y + 1 , z , grid_x , grid_y , grid_z ) == 0 )
692+ {
693+ int i ;
694+
695+ if (current_vert_idx + 12 > out_vertices_cap || current_index_idx + 6 > out_indices_cap )
696+ {
697+ return 0 ;
698+ }
699+
700+ for (i = 0 ; i < 4 ; ++ i )
701+ {
702+ out_vertices [current_vert_idx ++ ] = (float )x * voxel_size + half_voxel_size + mvx_face_vertices [2 ][i ][0 ] * half_voxel_size ;
703+ out_vertices [current_vert_idx ++ ] = (float )y * voxel_size + half_voxel_size + mvx_face_vertices [2 ][i ][1 ] * half_voxel_size ;
704+ out_vertices [current_vert_idx ++ ] = (float )z * voxel_size + half_voxel_size + mvx_face_vertices [2 ][i ][2 ] * half_voxel_size ;
705+ }
706+
707+ for (i = 0 ; i < 6 ; ++ i )
708+ {
709+ out_indices [current_index_idx ++ ] = (int )((current_vert_idx / 3 ) - 4 ) + mvx_face_indices [i ];
710+ }
711+ }
712+
713+ /* -Y neighbor */
714+ if (MVX_GET_VOXEL (voxels , x , y - 1 , z , grid_x , grid_y , grid_z ) == 0 )
715+ {
716+ int i ;
717+
718+ if (current_vert_idx + 12 > out_vertices_cap || current_index_idx + 6 > out_indices_cap )
719+ {
720+ return 0 ;
721+ }
722+
723+ for (i = 0 ; i < 4 ; ++ i )
724+ {
725+ out_vertices [current_vert_idx ++ ] = (float )x * voxel_size + half_voxel_size + mvx_face_vertices [3 ][i ][0 ] * half_voxel_size ;
726+ out_vertices [current_vert_idx ++ ] = (float )y * voxel_size + half_voxel_size + mvx_face_vertices [3 ][i ][1 ] * half_voxel_size ;
727+ out_vertices [current_vert_idx ++ ] = (float )z * voxel_size + half_voxel_size + mvx_face_vertices [3 ][i ][2 ] * half_voxel_size ;
728+ }
729+
730+ for (i = 0 ; i < 6 ; ++ i )
731+ {
732+ out_indices [current_index_idx ++ ] = (int )((current_vert_idx / 3 ) - 4 ) + mvx_face_indices [i ];
733+ }
734+ }
735+
736+ /* +Z neighbor */
737+ if (MVX_GET_VOXEL (voxels , x , y , z + 1 , grid_x , grid_y , grid_z ) == 0 )
738+ {
739+ int i ;
740+
741+ if (current_vert_idx + 12 > out_vertices_cap || current_index_idx + 6 > out_indices_cap )
742+ {
743+ return 0 ;
744+ }
745+
746+ for (i = 0 ; i < 4 ; ++ i )
747+ {
748+ out_vertices [current_vert_idx ++ ] = (float )x * voxel_size + half_voxel_size + mvx_face_vertices [0 ][i ][0 ] * half_voxel_size ;
749+ out_vertices [current_vert_idx ++ ] = (float )y * voxel_size + half_voxel_size + mvx_face_vertices [0 ][i ][1 ] * half_voxel_size ;
750+ out_vertices [current_vert_idx ++ ] = (float )z * voxel_size + half_voxel_size + mvx_face_vertices [0 ][i ][2 ] * half_voxel_size ;
751+ }
752+
753+ for (i = 0 ; i < 6 ; ++ i )
754+ {
755+ out_indices [current_index_idx ++ ] = (int )((current_vert_idx / 3 ) - 4 ) + mvx_face_indices [i ];
756+ }
757+ }
758+
759+ /* -Z neighbor */
760+ if (MVX_GET_VOXEL (voxels , x , y , z - 1 , grid_x , grid_y , grid_z ) == 0 )
761+ {
762+ int i ;
763+
764+ if (current_vert_idx + 12 > out_vertices_cap || current_index_idx + 6 > out_indices_cap )
765+ {
766+ return 0 ;
767+ }
768+
769+ for (i = 0 ; i < 4 ; ++ i )
770+ {
771+ out_vertices [current_vert_idx ++ ] = (float )x * voxel_size + half_voxel_size + mvx_face_vertices [1 ][i ][0 ] * half_voxel_size ;
772+ out_vertices [current_vert_idx ++ ] = (float )y * voxel_size + half_voxel_size + mvx_face_vertices [1 ][i ][1 ] * half_voxel_size ;
773+ out_vertices [current_vert_idx ++ ] = (float )z * voxel_size + half_voxel_size + mvx_face_vertices [1 ][i ][2 ] * half_voxel_size ;
774+ }
775+
776+ for (i = 0 ; i < 6 ; ++ i )
777+ {
778+ out_indices [current_index_idx ++ ] = (int )((current_vert_idx / 3 ) - 4 ) + mvx_face_indices [i ];
779+ }
780+ }
781+ }
782+ }
783+ }
784+ }
785+
786+ * out_vert_count = current_vert_idx ;
787+ * out_index_count = current_index_idx ;
788+
789+ return 1 ;
790+ }
791+
578792#endif /* MVX_H */
579793
580794/*
0 commit comments