@@ -44,6 +44,7 @@ public enum MVFaceDir
4444public class MVMainChunk
4545{
4646 public MVVoxelChunk voxelChunk ;
47+ public MVVoxelChunk alphaMaskChunk ;
4748
4849 public Color [ ] palatte ;
4950
@@ -321,7 +322,7 @@ public static Material DefaultMaterial {
321322 }
322323 }
323324
324- public static MVMainChunk LoadVOXFromData ( byte [ ] data ) {
325+ public static MVMainChunk LoadVOXFromData ( byte [ ] data , MVVoxelChunk alphaMask = null , bool generateFaces = true ) {
325326 using ( MemoryStream ms = new MemoryStream ( data ) ) {
326327 using ( BinaryReader br = new BinaryReader ( ms ) ) {
327328 MVMainChunk mainChunk = new MVMainChunk ( ) ;
@@ -378,7 +379,11 @@ public static MVMainChunk LoadVOXFromData(byte[] data) {
378379 }
379380 }
380381
381- GenerateFaces ( mainChunk . voxelChunk ) ;
382+ mainChunk . alphaMaskChunk = alphaMask ;
383+
384+ if ( generateFaces )
385+ GenerateFaces ( mainChunk . voxelChunk , alphaMask ) ;
386+
382387 if ( mainChunk . palatte == null )
383388 mainChunk . palatte = MVMainChunk . defaultPalatte ;
384389
@@ -387,7 +392,7 @@ public static MVMainChunk LoadVOXFromData(byte[] data) {
387392 }
388393 }
389394
390- public static MVMainChunk LoadVOX ( string path )
395+ public static MVMainChunk LoadVOX ( string path , MVVoxelChunk alphaMask = null , bool generateFaces = true )
391396 {
392397 byte [ ] bytes = File . ReadAllBytes ( path ) ;
393398 if ( bytes [ 0 ] != 'V' ||
@@ -398,10 +403,10 @@ public static MVMainChunk LoadVOX(string path)
398403 return null ;
399404 }
400405
401- return LoadVOXFromData ( bytes ) ;
406+ return LoadVOXFromData ( bytes , alphaMask , generateFaces ) ;
402407 }
403408
404- public static void GenerateFaces ( MVVoxelChunk voxelChunk )
409+ public static void GenerateFaces ( MVVoxelChunk voxelChunk , MVVoxelChunk alphaMask )
405410 {
406411 voxelChunk . faces = new MVFaceCollection [ 6 ] ;
407412 for ( int i = 0 ; i < 6 ; ++ i ) {
@@ -411,25 +416,28 @@ public static void GenerateFaces(MVVoxelChunk voxelChunk)
411416 for ( int x = 0 ; x < voxelChunk . sizeX ; ++ x ) {
412417 for ( int y = 0 ; y < voxelChunk . sizeY ; ++ y ) {
413418 for ( int z = 0 ; z < voxelChunk . sizeZ ; ++ z ) {
419+
420+ int alpha = alphaMask == null ? ( byte ) 0 : alphaMask . voxels [ x , y , z ] ;
421+
414422 // left right
415- if ( x == 0 || voxelChunk . voxels [ x - 1 , y , z ] == 0 )
416- voxelChunk . faces [ ( int ) MVFaceDir . XNeg ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
423+ if ( x == 0 || DetermineEmptyOrOtherAlphaVoxel ( voxelChunk , alphaMask , alpha , x - 1 , y , z ) )
424+ voxelChunk . faces [ ( int ) MVFaceDir . XNeg ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
417425
418- if ( x == voxelChunk . sizeX - 1 || voxelChunk . voxels [ x + 1 , y , z ] == 0 )
426+ if ( x == voxelChunk . sizeX - 1 || DetermineEmptyOrOtherAlphaVoxel ( voxelChunk , alphaMask , alpha , x + 1 , y , z ) )
419427 voxelChunk . faces [ ( int ) MVFaceDir . XPos ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
420428
421429 // up down
422- if ( y == 0 || voxelChunk . voxels [ x , y - 1 , z ] == 0 )
423- voxelChunk . faces [ ( int ) MVFaceDir . YNeg ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
430+ if ( y == 0 || DetermineEmptyOrOtherAlphaVoxel ( voxelChunk , alphaMask , alpha , x , y - 1 , z ) )
431+ voxelChunk . faces [ ( int ) MVFaceDir . YNeg ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
424432
425- if ( y == voxelChunk . sizeY - 1 || voxelChunk . voxels [ x , y + 1 , z ] == 0 )
433+ if ( y == voxelChunk . sizeY - 1 || DetermineEmptyOrOtherAlphaVoxel ( voxelChunk , alphaMask , alpha , x , y + 1 , z ) )
426434 voxelChunk . faces [ ( int ) MVFaceDir . YPos ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
427435
428436 // forward backward
429- if ( z == 0 || voxelChunk . voxels [ x , y , z - 1 ] == 0 )
430- voxelChunk . faces [ ( int ) MVFaceDir . ZNeg ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
437+ if ( z == 0 || DetermineEmptyOrOtherAlphaVoxel ( voxelChunk , alphaMask , alpha , x , y , z - 1 ) )
438+ voxelChunk . faces [ ( int ) MVFaceDir . ZNeg ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
431439
432- if ( z == voxelChunk . sizeZ - 1 || voxelChunk . voxels [ x , y , z + 1 ] == 0 )
440+ if ( z == voxelChunk . sizeZ - 1 || DetermineEmptyOrOtherAlphaVoxel ( voxelChunk , alphaMask , alpha , x , y , z + 1 ) )
433441 voxelChunk . faces [ ( int ) MVFaceDir . ZPos ] . colorIndices [ x , y , z ] = voxelChunk . voxels [ x , y , z ] ;
434442 }
435443 }
@@ -499,27 +507,27 @@ static int ReadPalattee(BinaryReader br, Color[] colors)
499507
500508 public static Mesh [ ] CreateMeshes ( MVMainChunk chunk , float sizePerVox )
501509 {
502- return CreateMeshesFromChunk ( chunk . voxelChunk , chunk . palatte , sizePerVox ) ;
510+ return CreateMeshesFromChunk ( chunk . voxelChunk , chunk . palatte , sizePerVox , chunk . alphaMaskChunk ) ;
503511 }
504512
505513 public static GameObject [ ] CreateVoxelGameObjects ( MVMainChunk chunk , Transform parent , Material mat , float sizePerVox )
506514 {
507- return CreateVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox ) ;
515+ return CreateVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox , chunk . alphaMaskChunk ) ;
508516 }
509517
510518 public static GameObject [ ] CreateVoxelGameObjects ( MVMainChunk chunk , Transform parent , Material mat , float sizePerVox , Vector3 origin )
511519 {
512- return CreateVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox , origin ) ;
520+ return CreateVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox , chunk . alphaMaskChunk , origin ) ;
513521 }
514522
515523 public static GameObject [ ] CreateIndividualVoxelGameObjects ( MVMainChunk chunk , Transform parent , Material mat , float sizePerVox )
516524 {
517- return CreateIndividualVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox ) ;
525+ return CreateIndividualVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox , chunk . alphaMaskChunk ) ;
518526 }
519527
520528 public static GameObject [ ] CreateIndividualVoxelGameObjects ( MVMainChunk chunk , Transform parent , Material mat , float sizePerVox , Vector3 origin )
521529 {
522- return CreateIndividualVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox , origin ) ;
530+ return CreateIndividualVoxelGameObjectsForChunk ( chunk . voxelChunk , chunk . palatte , parent , mat , sizePerVox , chunk . alphaMaskChunk , origin ) ;
523531 }
524532
525533 public static Mesh CubeMeshWithColor ( float size , Color c ) {
@@ -586,31 +594,41 @@ public static GameObject CreateGameObject(Transform parent, Vector3 pos, string
586594 return go ;
587595 }
588596
589- public static GameObject [ ] CreateIndividualVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox )
597+ public static GameObject [ ] CreateIndividualVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox , MVVoxelChunk alphaMask )
590598 {
591599 Vector3 origin = new Vector3 (
592600 ( float ) chunk . sizeX / 2 ,
593601 ( float ) chunk . sizeY / 2 ,
594602 ( float ) chunk . sizeZ / 2 ) ;
595603
596- return CreateIndividualVoxelGameObjectsForChunk ( chunk , palatte , parent , mat , sizePerVox , origin ) ;
604+ return CreateIndividualVoxelGameObjectsForChunk ( chunk , palatte , parent , mat , sizePerVox , alphaMask , origin ) ;
597605 }
598606
599- public static GameObject [ ] CreateIndividualVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox , Vector3 origin ) {
607+ public static GameObject [ ] CreateIndividualVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox , MVVoxelChunk alphaMask , Vector3 origin ) {
600608 List < GameObject > result = new List < GameObject > ( ) ;
601609
610+ if ( alphaMask != null && ( alphaMask . sizeX != chunk . sizeX || alphaMask . sizeY != chunk . sizeY || alphaMask . sizeZ != chunk . sizeZ ) )
611+ {
612+ Debug . LogErrorFormat ( "Unable to create meshes from chunk : Chunk's size ({0},{1},{2}) differs from alphaMask chunk's size ({3},{4},{5})" , chunk . sizeX , chunk . sizeY , chunk . sizeZ , alphaMask . sizeX , alphaMask . sizeY , alphaMask . sizeZ ) ;
613+ return result . ToArray ( ) ;
614+ }
615+
602616 for ( int x = 0 ; x < chunk . sizeX ; ++ x ) {
603617 for ( int y = 0 ; y < chunk . sizeY ; ++ y ) {
604618 for ( int z = 0 ; z < chunk . sizeZ ; ++ z ) {
605619
606620 if ( chunk . voxels [ x , y , z ] != 0 ) {
607621 float px = ( x - origin . x + 0.5f ) * sizePerVox , py = ( y - origin . y + 0.5f ) * sizePerVox , pz = ( z - origin . z + 0.5f ) * sizePerVox ;
622+ Color c = palatte [ chunk . voxels [ x , y , z ] - 1 ] ;
623+
624+ if ( alphaMask != null && alphaMask . voxels [ x , y , z ] != 0 )
625+ c . a = ( float ) ( alphaMask . voxels [ x , y , z ] - 1 ) / 255 ;
608626
609627 GameObject go = CreateGameObject (
610628 parent ,
611629 new Vector3 ( px , py , pz ) ,
612630 string . Format ( "Voxel ({0}, {1}, {2})" , x , y , z ) ,
613- MVImporter . CubeMeshWithColor ( sizePerVox , palatte [ chunk . voxels [ x , y , z ] - 1 ] ) ,
631+ MVImporter . CubeMeshWithColor ( sizePerVox , c ) ,
614632 mat ) ;
615633
616634 MVVoxModelVoxel v = go . AddComponent < MVVoxModelVoxel > ( ) ;
@@ -625,20 +643,20 @@ public static GameObject[] CreateIndividualVoxelGameObjectsForChunk(MVVoxelChunk
625643 return result . ToArray ( ) ;
626644 }
627645
628- public static GameObject [ ] CreateVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox )
646+ public static GameObject [ ] CreateVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox , MVVoxelChunk alphaMask )
629647 {
630648 Vector3 origin = new Vector3 (
631649 ( float ) chunk . sizeX / 2 ,
632650 ( float ) chunk . sizeY / 2 ,
633651 ( float ) chunk . sizeZ / 2 ) ;
634652
635- return CreateVoxelGameObjectsForChunk ( chunk , palatte , parent , mat , sizePerVox , origin ) ;
653+ return CreateVoxelGameObjectsForChunk ( chunk , palatte , parent , mat , sizePerVox , alphaMask , origin ) ;
636654 }
637655
638- public static GameObject [ ] CreateVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox , Vector3 origin ) {
656+ public static GameObject [ ] CreateVoxelGameObjectsForChunk ( MVVoxelChunk chunk , Color [ ] palatte , Transform parent , Material mat , float sizePerVox , MVVoxelChunk alphaMask , Vector3 origin ) {
639657 List < GameObject > result = new List < GameObject > ( ) ;
640658
641- Mesh [ ] meshes = CreateMeshesFromChunk ( chunk , palatte , sizePerVox , origin ) ;
659+ Mesh [ ] meshes = CreateMeshesFromChunk ( chunk , palatte , sizePerVox , alphaMask , origin ) ;
642660
643661 int index = 0 ;
644662 foreach ( Mesh mesh in meshes ) {
@@ -661,18 +679,24 @@ public static GameObject[] CreateVoxelGameObjectsForChunk(MVVoxelChunk chunk, Co
661679 return result . ToArray ( ) ;
662680 }
663681
664- public static Mesh [ ] CreateMeshesFromChunk ( MVVoxelChunk chunk , Color [ ] palatte , float sizePerVox )
682+ public static Mesh [ ] CreateMeshesFromChunk ( MVVoxelChunk chunk , Color [ ] palatte , float sizePerVox , MVVoxelChunk alphaMask )
665683 {
666684 Vector3 origin = new Vector3 (
667685 ( float ) chunk . sizeX / 2 ,
668686 ( float ) chunk . sizeY / 2 ,
669687 ( float ) chunk . sizeZ / 2 ) ;
670688
671- return CreateMeshesFromChunk ( chunk , palatte , sizePerVox , origin ) ;
689+ return CreateMeshesFromChunk ( chunk , palatte , sizePerVox , alphaMask , origin ) ;
672690 }
673691
674- public static Mesh [ ] CreateMeshesFromChunk ( MVVoxelChunk chunk , Color [ ] palatte , float sizePerVox , Vector3 origin )
692+ public static Mesh [ ] CreateMeshesFromChunk ( MVVoxelChunk chunk , Color [ ] palatte , float sizePerVox , MVVoxelChunk alphaMask , Vector3 origin )
675693 {
694+ if ( alphaMask != null && ( alphaMask . sizeX != chunk . sizeX || alphaMask . sizeY != chunk . sizeY || alphaMask . sizeZ != chunk . sizeZ ) )
695+ {
696+ Debug . LogErrorFormat ( "Unable to create meshes from chunk : Chunk's size ({0},{1},{2}) differs from alphaMask chunk's size ({3},{4},{5})" , chunk . sizeX , chunk . sizeY , chunk . sizeZ , alphaMask . sizeX , alphaMask . sizeY , alphaMask . sizeZ ) ;
697+ return new Mesh [ ] { } ;
698+ }
699+
676700 List < Vector3 > verts = new List < Vector3 > ( ) ;
677701 List < Vector3 > normals = new List < Vector3 > ( ) ;
678702 List < Color > colors = new List < Color > ( ) ;
@@ -702,6 +726,7 @@ public static Mesh[] CreateMeshesFromChunk(MVVoxelChunk chunk, Color[] palatte,
702726 for ( int z = 0 ; z < chunk . sizeZ ; ++ z ) {
703727
704728 int cidx = chunk . faces [ f ] . colorIndices [ x , y , z ] ;
729+ int alpha = alphaMask == null ? ( byte ) 0 : alphaMask . voxels [ x , y , z ] ;
705730
706731 if ( cidx != 0 ) {
707732 float px = ( x - origin . x + 0.5f ) * sizePerVox , py = ( y - origin . y + 0.5f ) * sizePerVox , pz = ( z - origin . z + 0.5f ) * sizePerVox ;
@@ -712,15 +737,15 @@ public static Mesh[] CreateMeshesFromChunk(MVVoxelChunk chunk, Color[] palatte,
712737 case 0 :
713738 {
714739 ry = y + 1 ;
715- while ( ry < chunk . sizeY && chunk . faces [ f ] . colorIndices [ x , ry , z ] == cidx )
740+ while ( ry < chunk . sizeY && CompareColor ( cidx , alpha , chunk , alphaMask , f , x , ry , z ) )
716741 ry ++ ;
717742 ry -- ;
718743
719744 rz = z + 1 ;
720745 while ( rz < chunk . sizeZ ) {
721746 bool inc = true ;
722747 for ( int k = y ; k <= ry ; ++ k ) {
723- inc = inc & ( chunk . faces [ f ] . colorIndices [ x , k , rz ] == cidx ) ;
748+ inc = inc & ( CompareColor ( cidx , alpha , chunk , alphaMask , f , x , k , rz ) ) ;
724749 }
725750
726751 if ( inc )
@@ -736,15 +761,15 @@ public static Mesh[] CreateMeshesFromChunk(MVVoxelChunk chunk, Color[] palatte,
736761 case 2 :
737762 {
738763 rx = x + 1 ;
739- while ( rx < chunk . sizeX && chunk . faces [ f ] . colorIndices [ rx , y , z ] == cidx )
764+ while ( rx < chunk . sizeX && CompareColor ( cidx , alpha , chunk , alphaMask , f , rx , y , z ) )
740765 rx ++ ;
741766 rx -- ;
742767
743768 rz = z + 1 ;
744769 while ( rz < chunk . sizeZ ) {
745770 bool inc = true ;
746771 for ( int k = x ; k <= rx ; ++ k ) {
747- inc = inc & ( chunk . faces [ f ] . colorIndices [ k , y , rz ] == cidx ) ;
772+ inc = inc & ( CompareColor ( cidx , alpha , chunk , alphaMask , f , k , y , rz ) ) ;
748773 }
749774
750775 if ( inc )
@@ -760,15 +785,15 @@ public static Mesh[] CreateMeshesFromChunk(MVVoxelChunk chunk, Color[] palatte,
760785 case 4 :
761786 {
762787 rx = x + 1 ;
763- while ( rx < chunk . sizeX && chunk . faces [ f ] . colorIndices [ rx , y , z ] == cidx )
788+ while ( rx < chunk . sizeX && CompareColor ( cidx , alpha , chunk , alphaMask , f , rx , y , z ) )
764789 rx ++ ;
765790 rx -- ;
766791
767792 ry = y + 1 ;
768793 while ( ry < chunk . sizeY ) {
769794 bool inc = true ;
770795 for ( int k = x ; k <= rx ; ++ k ) {
771- inc = inc & ( chunk . faces [ f ] . colorIndices [ k , ry , z ] == cidx ) ;
796+ inc = inc & ( CompareColor ( cidx , alpha , chunk , alphaMask , f , k , ry , z ) ) ;
772797 }
773798
774799 if ( inc )
@@ -847,6 +872,9 @@ public static Mesh[] CreateMeshesFromChunk(MVVoxelChunk chunk, Color[] palatte,
847872 // color index starts with 1
848873 Color c = palatte [ cidx - 1 ] ;
849874
875+ if ( alpha != 0 )
876+ c . a = ( float ) ( alpha - 1 ) / 255 ;
877+
850878 colors . Add ( c ) ;
851879 colors . Add ( c ) ;
852880 colors . Add ( c ) ;
@@ -901,5 +929,25 @@ public static Mesh[] CreateMeshesFromChunk(MVVoxelChunk chunk, Color[] palatte,
901929
902930 return result . ToArray ( ) ;
903931 }
904- }
905932
933+ private static bool CompareColor ( int cidx , int alpha , MVVoxelChunk chunk , MVVoxelChunk alphaChunk , int f , int x , int y , int z )
934+ {
935+ if ( alphaChunk == null )
936+ return chunk . faces [ f ] . colorIndices [ x , y , z ] == cidx ;
937+ else
938+ return chunk . faces [ f ] . colorIndices [ x , y , z ] == cidx && alphaChunk . voxels [ x , y , z ] == alpha ;
939+ }
940+
941+ private static bool DetermineEmptyOrOtherAlphaVoxel ( MVVoxelChunk voxelChunk , MVVoxelChunk alphaMask , int a , int x , int y , int z )
942+ {
943+ bool isEmpty = voxelChunk . voxels [ x , y , z ] == 0 ;
944+
945+ if ( alphaMask == null )
946+ return isEmpty ;
947+ else
948+ {
949+ bool otherAlpha = alphaMask . voxels [ x , y , z ] != a ;
950+ return isEmpty || otherAlpha ;
951+ }
952+ }
953+ }
0 commit comments