@@ -305,7 +305,7 @@ int main(int argc, char **argv)
305
305
return 1 ;
306
306
}
307
307
if (!isAlphaWorld (filename)) {
308
- printf (" Error: Given path does not contain an alpha/beta world.\n " );
308
+ printf (" Error: Given path does not contain a Minecraft world.\n " );
309
309
return 1 ;
310
310
}
311
311
if (g_Hell) {
@@ -327,19 +327,16 @@ int main(int argc, char **argv)
327
327
}
328
328
filename = tmp;
329
329
}
330
- { // Figure out whether this is the old save format or McRegion
331
- char tmp[1000 ];
332
- snprintf (tmp, 1000 , " %s/region" , filename);
333
- if (dirExists (tmp)) {
334
- printf (" McRegion world format detected.\n " );
335
- g_RegionFormat = true ;
330
+ // Figure out whether this is the old save format or McRegion or Anvil
331
+ g_WorldFormat = getWorldFormat (filename);
332
+
333
+ if (g_WorldFormat < 2 ) {
334
+ if (g_MapsizeY > CHUNKSIZE_Y) {
335
+ g_MapsizeY = CHUNKSIZE_Y;
336
+ }
337
+ if (g_MapminY > CHUNKSIZE_Y) {
338
+ g_MapminY = CHUNKSIZE_Y;
336
339
}
337
- }
338
- if (g_MapsizeY > CHUNKSIZE_Y) {
339
- g_MapsizeY = CHUNKSIZE_Y;
340
- }
341
- if (g_MapminY > CHUNKSIZE_Y) {
342
- g_MapminY = CHUNKSIZE_Y;
343
340
}
344
341
if (wholeworld && !scanWorldDirectory (filename)) {
345
342
printf (" Error accessing terrain at '%s'\n " , filename);
@@ -353,7 +350,10 @@ int main(int argc, char **argv)
353
350
printf (" Nothing to render: -min Y has to be < -max/-height Y\n " );
354
351
return 1 ;
355
352
}
353
+ g_SectionMin = g_MapminY >> SECTION_Y_SHIFT;
354
+ g_SectionMax = (g_MapsizeY - 1 ) >> SECTION_Y_SHIFT;
356
355
g_MapsizeY -= g_MapminY;
356
+ printf (" MinY: %d ... MaxY: %d ... MinSecY: %d ... MaxSecY: %d\n " , g_MapminY, g_MapsizeY, g_SectionMin, g_SectionMax);
357
357
// Whole area to be rendered, in chunks
358
358
// If -mem is omitted or high enough, this won't be needed
359
359
g_TotalFromChunkX = g_FromChunkX;
@@ -477,6 +477,12 @@ int main(int argc, char **argv)
477
477
createImageBuffer (bitmapX, bitmapY, splitImage);
478
478
}
479
479
480
+ // Precompute brightness adjustment factor
481
+ float *brightnessLookup = new float [g_MapsizeY];
482
+ for (int y = 0 ; y < g_MapsizeY; ++y) {
483
+ brightnessLookup[y] = ((100 .0f / (1 .0f + exp (- (1 .3f * (float (y) * 128 .0f / g_MapsizeY) / 16 .0f ) + 6 .0f ))) - 91 ); // thx Donkey Kong
484
+ }
485
+
480
486
// Now here's the loop rendering all the required parts of the image.
481
487
// All the vars previously used to define bounds will be set on each loop,
482
488
// to create something like a virtual window inside the map.
@@ -580,15 +586,15 @@ int main(int argc, char **argv)
580
586
//
581
587
const int bmpPosX = int ((g_MapsizeZ - z - CHUNKSIZE_Z) * 2 + (x - CHUNKSIZE_X) * 2 + (splitImage ? -2 : bitmapStartX - cropLeft));
582
588
int bmpPosY = int (g_MapsizeY * g_OffsetY + z + x - CHUNKSIZE_Z - CHUNKSIZE_X + (splitImage ? 0 : bitmapStartY - cropTop)) + 2 - (HEIGHTAT (x, z) & 0xFF ) * g_OffsetY;
583
- const size_t max = (HEIGHTAT (x, z) & 0xFF00 ) >> 8 ;
584
- for (size_t y = uint8_t (HEIGHTAT (x, z)); y < max; ++y) {
589
+ const int max = (HEIGHTAT (x, z) & 0xFF00 ) >> 8 ;
590
+ for (int y = uint8_t (HEIGHTAT (x, z)); y < max; ++y) {
585
591
bmpPosY -= g_OffsetY;
586
592
uint8_t &c = BLOCKAT (x, y, z);
587
593
if (c == AIR) {
588
594
continue ;
589
595
}
590
596
// float col = float(y) * .78f - 91;
591
- float brightnessAdjustment = ( 100 . 0f / ( 1 . 0f + exp (- ( 1 . 3f * float (y) / 16 . 0f ) + 6 . 0f ))) - 91 ; // thx Donkey Kong
597
+ float brightnessAdjustment = brightnessLookup[y];
592
598
if (g_BlendUnderground) {
593
599
brightnessAdjustment -= 168 ;
594
600
}
@@ -735,7 +741,7 @@ void optimizeTerrain2(int cropLeft, int cropRight)
735
741
for (int z = CHUNKSIZE_Z; z < maxZ; ++z) {
736
742
const uint8_t *block = &BLOCKAT (x, 0 , z); // Get the lowest block at that point
737
743
int highest = 0 , lowest = 0xFF ; // remember lowest and highest block which are visible to limit the Y-for-loop later
738
- for (size_t y = 0 ; y < g_MapsizeY; ++y) { // Go up
744
+ for (int y = 0 ; y < g_MapsizeY; ++y) { // Go up
739
745
uint8_t ¤t = blocked[((y+offsetY) % g_MapsizeY) + (offsetZ % modZ)];
740
746
if (current) { // Block is hidden, remove
741
747
#ifdef _DEBUG
@@ -758,7 +764,7 @@ void optimizeTerrain2(int cropLeft, int cropRight)
758
764
blocked[(offsetY % g_MapsizeY) + (offsetZ % modZ)] = 0 ;
759
765
offsetZ += g_MapsizeY;
760
766
}
761
- for (size_t y = 0 ; y < g_MapsizeY; ++y) {
767
+ for (int y = 0 ; y < g_MapsizeY; ++y) {
762
768
blocked[y + (offsetGlobal % modZ)] = 0 ;
763
769
}
764
770
offsetGlobal += g_MapsizeY;
@@ -780,24 +786,23 @@ void optimizeTerrain3()
780
786
gBlocksRemoved = 0 ;
781
787
#endif
782
788
printProgress (0 , 10 );
783
- const int top = (int )g_MapsizeY;
784
789
// Helper arrays to remember which block is blocked from being seen. This allows to traverse the array in a slightly more sequential way, which leads to better usage of the CPU cache
785
- uint8_t blocked[CHUNKSIZE_Y *3 ];
790
+ uint8_t * blocked = new uint8_t [g_MapsizeY *3 ];
786
791
const int max = (int )MIN (g_MapsizeX - CHUNKSIZE_X * 2 , g_MapsizeZ - CHUNKSIZE_Z * 2 );
787
792
const int maxX = int (g_MapsizeX - CHUNKSIZE_X - 1 );
788
793
const int maxZ = int (g_MapsizeZ - CHUNKSIZE_Z - 1 );
789
794
const size_t maxProgress = size_t (maxX + maxZ);
790
795
// The following needs to be done twice, once for the X-Y front plane, once for the Z-Y front plane
791
796
for (int x = CHUNKSIZE_X; x <= maxX; ++x) {
792
- memset (blocked, 0 , CHUNKSIZE_Y *3 ); // Nothing is blocked at first
797
+ memset (blocked, 0 , g_MapsizeY *3 ); // Nothing is blocked at first
793
798
int offset = 0 ; // The helper array had to be shifted after each run of the inner most loop. As this is expensive, just use an offset that increases instead
794
799
const int max2 = MIN (max, x - CHUNKSIZE_X + 1 ); // Block array will be traversed diagonally, determine how many blocks there are
795
800
for (int i = 0 ; i < max2; ++i) { // This traverses the block array diagonally, which would be upwards in the image
796
- const int blockedOffset = CHUNKSIZE_Y * (i % 3 );
801
+ const int blockedOffset = g_MapsizeY * (i % 3 );
797
802
uint8_t *block = &BLOCKAT (x - i, 0 , maxZ - i); // Get the lowest block at that point
798
803
int highest = 0 , lowest = 0xFF ;
799
- for (int j = 0 ; j < top ; ++j) { // Go up
800
- if (blocked[blockedOffset + (j+offset) % top ]) { // Block is hidden, remove
804
+ for (int j = 0 ; j < g_MapsizeY ; ++j) { // Go up
805
+ if (blocked[blockedOffset + (j+offset) % g_MapsizeY ]) { // Block is hidden, remove
801
806
#ifdef _DEBUG
802
807
if (*block != AIR) {
803
808
++gBlocksRemoved ;
@@ -808,31 +813,31 @@ void optimizeTerrain3()
808
813
lowest = j;
809
814
}
810
815
if (colors[*block][PALPHA] == 255 ) { // Block is not hidden, do not remove, but mark spot as blocked for next iteration
811
- blocked[blockedOffset + (j+offset) % top ] = 1 ;
816
+ blocked[blockedOffset + (j+offset) % g_MapsizeY ] = 1 ;
812
817
}
813
818
if (*block != AIR) highest = j;
814
819
}
815
820
++block; // Go up
816
821
}
817
822
HEIGHTAT (x - i, maxZ - i) = (((uint16_t )highest + 1 ) << 8 ) | (uint16_t )lowest;
818
- blocked[blockedOffset + ((offset + 1 ) % top )] = 0 ; // This will be the array index responsible for the top most block in the next itaration. Set it to 0 as it can't be hidden.
819
- blocked[blockedOffset + (offset % top )] = 0 ;
823
+ blocked[blockedOffset + ((offset + 1 ) % g_MapsizeY )] = 0 ; // This will be the array index responsible for the top most block in the next itaration. Set it to 0 as it can't be hidden.
824
+ blocked[blockedOffset + (offset % g_MapsizeY )] = 0 ;
820
825
if (i % 3 == 2 ) {
821
826
offset += 2 ; // Increase offset, as block at height n in current row will hide block at n-1 in next row
822
827
}
823
828
}
824
829
printProgress (size_t (x), maxProgress);
825
830
}
826
831
for (int z = CHUNKSIZE_Z; z < maxZ; ++z) {
827
- memset (blocked, 0 , CHUNKSIZE_Y *3 );
832
+ memset (blocked, 0 , g_MapsizeY *3 );
828
833
int offset = 0 ;
829
834
const int max2 = MIN (max, z - CHUNKSIZE_Z + 1 );
830
835
for (int i = 0 ; i < max2; ++i) {
831
- const int blockedOffset = CHUNKSIZE_Y * (i % 3 );
836
+ const int blockedOffset = g_MapsizeY * (i % 3 );
832
837
uint8_t *block = &BLOCKAT (maxX - i, 0 , z - i);
833
838
int highest = 0 , lowest = 0xFF ;
834
- for (int j = 0 ; j < top ; ++j) {
835
- if (blocked[blockedOffset + (j+offset) % top ]) {
839
+ for (int j = 0 ; j < g_MapsizeY ; ++j) {
840
+ if (blocked[blockedOffset + (j+offset) % g_MapsizeY ]) {
836
841
#ifdef _DEBUG
837
842
if (*block != AIR) {
838
843
++gBlocksRemoved ;
@@ -843,21 +848,22 @@ void optimizeTerrain3()
843
848
lowest = j;
844
849
}
845
850
if (colors[*block][PALPHA] == 255 ) {
846
- blocked[blockedOffset + (j+offset) % top ] = 1 ;
851
+ blocked[blockedOffset + (j+offset) % g_MapsizeY ] = 1 ;
847
852
}
848
853
if (*block != AIR) highest = j;
849
854
}
850
855
++block;
851
856
}
852
857
HEIGHTAT (maxX - i, z - i) = (((uint16_t )highest + 1 ) << 8 ) | (uint16_t )lowest;
853
- blocked[blockedOffset + ((offset + 1 ) % top )] = 0 ;
854
- blocked[blockedOffset + (offset % top )] = 0 ;
858
+ blocked[blockedOffset + ((offset + 1 ) % g_MapsizeY )] = 0 ;
859
+ blocked[blockedOffset + (offset % g_MapsizeY )] = 0 ;
855
860
if (i % 3 == 2 ) {
856
861
offset += 2 ;
857
862
}
858
863
}
859
864
printProgress (size_t (z + maxX), maxProgress);
860
865
}
866
+ delete[] blocked;
861
867
printProgress (10 , 10 );
862
868
#ifdef _DEBUG
863
869
printf (" Removed %lu blocks\n " , (unsigned long ) gBlocksRemoved );
@@ -875,7 +881,7 @@ void undergroundMode(bool explore)
875
881
for (size_t x = CHUNKSIZE_X; x < g_MapsizeX - CHUNKSIZE_X; ++x) {
876
882
printProgress (x - CHUNKSIZE_X, g_MapsizeX);
877
883
for (size_t z = CHUNKSIZE_Z; z < g_MapsizeZ - CHUNKSIZE_Z; ++z) {
878
- for (size_t y = 0 ; y < MIN (g_MapsizeY, 64 ) - 1 ; y++) {
884
+ for (int y = 0 ; y < MIN (g_MapsizeY, 64 ) - 1 ; y++) {
879
885
if (BLOCKAT (x, y, z) == TORCH) {
880
886
// Torch
881
887
BLOCKAT (x, y, z) = AIR;
@@ -915,7 +921,7 @@ void undergroundMode(bool explore)
915
921
for (size_t z = 0 ; z < g_MapsizeZ; ++z) {
916
922
size_t ground = 0 ;
917
923
size_t cave = 0 ;
918
- for (size_t y = g_MapsizeY - 1 ; y < g_MapsizeY; --y) {
924
+ for (int y = g_MapsizeY - 1 ; y < g_MapsizeY; --y) {
919
925
uint8_t &c = BLOCKAT (x, y, z);
920
926
if (c != AIR && cave > 0 ) { // Found a cave, leave floor
921
927
if (c == GRASS || c == LEAVES || c == SNOW || GETLIGHTAT (x, y, z) == 0 ) {
@@ -1019,19 +1025,19 @@ void writeInfoFile(const char* file, int xo, int yo, int bitmapX, int bitmapY)
1019
1025
char *direction = NULL ;
1020
1026
if (g_Orientation == North) {
1021
1027
xo += (g_TotalToChunkZ * CHUNKSIZE_Z - g_FromChunkX * CHUNKSIZE_X) * 2 + 4 ;
1022
- yo -= (g_TotalFromChunkX * CHUNKSIZE_X + g_TotalFromChunkZ * CHUNKSIZE_Z) - CHUNKSIZE_Y * g_OffsetY;
1028
+ yo -= (g_TotalFromChunkX * CHUNKSIZE_X + g_TotalFromChunkZ * CHUNKSIZE_Z) - g_MapsizeY * g_OffsetY;
1023
1029
direction = (char *)" North" ;
1024
1030
} else if (g_Orientation == South) {
1025
1031
xo += (g_TotalToChunkX * CHUNKSIZE_X - g_TotalFromChunkZ * CHUNKSIZE_Z) * 2 + 4 ;
1026
- yo += ((g_TotalToChunkX) * CHUNKSIZE_X + (g_TotalToChunkZ) * CHUNKSIZE_Z) + CHUNKSIZE_Y * g_OffsetY;
1032
+ yo += ((g_TotalToChunkX) * CHUNKSIZE_X + (g_TotalToChunkZ) * CHUNKSIZE_Z) + g_MapsizeY * g_OffsetY;
1027
1033
direction = (char *)" South" ;
1028
1034
} else if (g_Orientation == East) {
1029
1035
xo -= (g_TotalFromChunkX * CHUNKSIZE_X + g_TotalFromChunkZ * CHUNKSIZE_Z) * g_OffsetY - 6 ;
1030
- yo += ((g_TotalToChunkX) * CHUNKSIZE_X - g_TotalFromChunkZ * CHUNKSIZE_Z) + CHUNKSIZE_Y * g_OffsetY;
1036
+ yo += ((g_TotalToChunkX) * CHUNKSIZE_X - g_TotalFromChunkZ * CHUNKSIZE_Z) + g_MapsizeY * g_OffsetY;
1031
1037
direction = (char *)" East" ;
1032
1038
} else {
1033
1039
xo += (g_TotalToChunkX * CHUNKSIZE_X + g_TotalToChunkZ * CHUNKSIZE_Z) * g_OffsetY + 2 ;
1034
- yo += ((g_TotalToChunkZ) * CHUNKSIZE_Z - g_TotalFromChunkX * CHUNKSIZE_X) + CHUNKSIZE_Y * g_OffsetY;
1040
+ yo += ((g_TotalToChunkZ) * CHUNKSIZE_Z - g_TotalFromChunkX * CHUNKSIZE_X) + g_MapsizeY * g_OffsetY;
1035
1041
direction = (char *)" West" ;
1036
1042
}
1037
1043
FILE *fh = fopen (file, " w" );
@@ -1106,8 +1112,8 @@ void printHelp(char *binary)
1106
1112
" -skylight use skylight when rendering map (shadows below trees etc.)\n "
1107
1113
" hint: using this with -night makes a difference\n "
1108
1114
" -noise VAL adds some noise to certain blocks, reasonable values are 0-20\n "
1109
- " -height VAL maximum height at which blocks will be rendered (1-%d) \n "
1110
- " -min/max VAL minimum/maximum Y index (height) of blocks to render (0-127) \n "
1115
+ " -height VAL maximum height at which blocks will be rendered\n "
1116
+ " -min/max VAL minimum/maximum Y index (height) of blocks to render\n "
1111
1117
" -file NAME sets the output filename to 'NAME'; default is output.png\n "
1112
1118
" -mem VAL sets the amount of memory (in MiB) used for rendering. mcmap\n "
1113
1119
" will use incremental rendering or disk caching to stick to\n "
@@ -1146,5 +1152,5 @@ void printHelp(char *binary)
1146
1152
" - This would render the same world but at night, and only\n "
1147
1153
" from chunk (-10 -10) to chunk (10 10)\n "
1148
1154
#endif
1149
- , binary,( int )CHUNKSIZE_Y, binary, binary);
1155
+ , binary, binary, binary);
1150
1156
}
0 commit comments