2929import com .google .gson .GsonBuilder ;
3030import com .google .gson .stream .JsonWriter ;
3131import de .bluecolored .bluemap .core .util .InstancePool ;
32+ import de .bluecolored .bluemap .core .util .MergeSort ;
3233import de .bluecolored .bluemap .core .util .math .MatrixM3f ;
3334import de .bluecolored .bluemap .core .util .math .MatrixM4f ;
3435import de .bluecolored .bluemap .core .util .math .VectorM3f ;
3536
36- import java .io .BufferedWriter ;
37- import java .io .IOException ;
38- import java .io .OutputStream ;
39- import java .io .OutputStreamWriter ;
37+ import java .io .*;
4038import java .nio .charset .StandardCharsets ;
4139import java .util .UUID ;
4240
@@ -64,7 +62,7 @@ public class HiresTileModel {
6462 private double [] position ;
6563 private float [] color , uv , ao ;
6664 private byte [] sunlight , blocklight ;
67- private int [] materialIndex ;
65+ private int [] materialIndex , materialIndexSort , materialIndexSortSupport ;
6866
6967 public HiresTileModel (int initialCapacity ) {
7068 if (initialCapacity < 0 ) throw new IllegalArgumentException ("initialCapacity is negative" );
@@ -388,6 +386,9 @@ private void setCapacity(int capacity) {
388386 sunlight = new byte [capacity * FI_SUNLIGHT ];
389387 blocklight = new byte [capacity * FI_BLOCKLIGHT ];
390388 materialIndex = new int [capacity * FI_MATERIAL_INDEX ];
389+
390+ materialIndexSort = new int [materialIndex .length ];
391+ materialIndexSortSupport = new int [materialIndex .length ];
391392 }
392393
393394 public void writeBufferGeometryJson (OutputStream out ) throws IOException {
@@ -396,6 +397,8 @@ public void writeBufferGeometryJson(OutputStream out) throws IOException {
396397 Gson gson = new GsonBuilder ().create ();
397398 JsonWriter json = gson .newJsonWriter (new BufferedWriter (new OutputStreamWriter (out , StandardCharsets .UTF_8 ), 81920 ));
398399
400+ Writer w = null ;
401+
399402 json .beginObject (); // main-object
400403 json .name ("tileGeometry" ).beginObject (); // tile-geometry-object
401404
@@ -583,20 +586,20 @@ private void writeMaterialGroups(JsonWriter json) throws IOException {
583586 material = materialIndex [i ];
584587
585588 if (material != lastMaterial ) {
586- json .name ("count" ).value ((i - groupStart ) * 3 );
589+ json .name ("count" ).value ((i - groupStart ) * 3L );
587590 json .endObject ();
588591
589592 groupStart = i ;
590593
591594 json .beginObject ();
592595 json .name ("materialIndex" ).value (material );
593- json .name ("start" ).value (groupStart * 3 );
596+ json .name ("start" ).value (groupStart * 3L );
594597 }
595598
596599 lastMaterial = material ;
597600 }
598601
599- json .name ("count" ).value ((miSize - groupStart ) * 3 );
602+ json .name ("count" ).value ((miSize - groupStart ) * 3L );
600603 json .endObject ();
601604
602605 }
@@ -611,34 +614,30 @@ private void writeRounded(JsonWriter json, double value) throws IOException {
611614 else json .value (d );
612615 }
613616
614- /**
615- * Does an optimized selection sort to sort all faces based on their material-index.
616- * A selection sort is chosen, because it requires the least amount of swaps, which seem (untested) to be the most expensive operation here
617- */
618617 private void sort () {
619618 if (size <= 1 ) return ; // nothing to sort
620619
621- int prev = Integer . MIN_VALUE , min , minIndex , i , j ;
622- for (i = 0 ; i < size - 1 ; i ++){
623- minIndex = i ;
624- min = materialIndex [ minIndex ] ;
625- if ( min <= prev ) continue ; // shortcut
620+ // initialize material-index-sort
621+ for (int i = 0 ; i < size ; i ++) {
622+ materialIndexSort [ i ] = i ;
623+ materialIndexSortSupport [ i ] = i ;
624+ }
626625
627- for (j = i + 1 ; j < size ; j ++){
628- if (materialIndex [j ] < min ){
629- minIndex = j ;
630- min = materialIndex [minIndex ];
631- }
632- }
626+ // sort
627+ MergeSort .mergeSortInt (materialIndexSort , 0 , size , this ::compareMaterialIndex , materialIndexSortSupport );
633628
634- if (minIndex != i ) {
635- swap (minIndex , i );
629+ // move
630+ for (int i = 0 ; i < size ; i ++) {
631+ while (materialIndexSort [i ] != i ) {
632+ swap (i , materialIndexSort [i ]);
636633 }
637-
638- prev = min ;
639634 }
640635 }
641636
637+ private int compareMaterialIndex (int i1 , int i2 ) {
638+ return Integer .compare (materialIndex [i1 ], materialIndex [i2 ]);
639+ }
640+
642641 private void swap (int face1 , int face2 ) {
643642 int i , if1 , if2 , vi ;
644643 double vd ;
@@ -695,6 +694,11 @@ private void swap(int face1, int face2) {
695694 vi = materialIndex [face1 ];
696695 materialIndex [face1 ] = materialIndex [face2 ];
697696 materialIndex [face2 ] = vi ;
697+
698+ //swap material-index-sort (assuming FI_MATERIAL_INDEX = 1)
699+ vi = materialIndexSort [face1 ];
700+ materialIndexSort [face1 ] = materialIndexSort [face2 ];
701+ materialIndexSort [face2 ] = vi ;
698702 }
699703
700704 private static void calculateSurfaceNormal (
0 commit comments