Höhedaten von Landschaften effizient speichern, Problem bei comprimieren


FBIagent

Erfahrenes Mitglied
Guten Abend,

ich schreibe gerade, wie im Betreff schon erwähnt, ein Programm, welches Höhendaten
von Landschaften etwas effizienter speichert. Was ich mit effizienter meine?

Ich habe eine Spielewelt, die ich in 32*32 Regionen unterteile. Jede Region beinhaltet
256*256 Zellen und jede dieser Zellen ist noch einmal unterteilt in 8*8 Blöcke. Die
Blöcke sollen hierbei beliebig viele Höheninfomationen beinhalten können. Eine
Höheninformation eines Blocks ist ein 2 byte shot. Weiterhin wird für jede
Höheninformation ein 1 byte char benötigt(NSWE), um überprüfen zu können ob der
Spieler einen Block auf dieser Höhe aus einr bestimten Richtung betreten kann oder nicht.

Eine Höheninfomationsdatei ist eine Region.

Um effizienter ohne jeklichen Datenverlust zu spiechern versuche ich folgendes:
1. Falls alle Blöcke in einer Zelle garkeine Höheninformationen beinhalten, schreibe ich eine 0 in die Datei.
2. Falls alle Blöcke in einer Zelle genau eine Höheninfomation beinhalten, wird eine 1 geschrieben und eine Höheninformation.
3. Wenn Blöcke der Zelle 0 und 1 Höheninfomationen beinhalten und mindestens ein Block 1 Höheninfomation hat wird eine 2 geschrieben, und 8*8 Zelleninformationen. Falls ein Block keine Höheninfomationen enthält wird als block typ 0 geschrieben, falls doch wird eine 1 als block typ geschrieben und danach die höhen und NSWE Werte.
4. Blöcke in Zellen haben 0 und mehr Höheninfomationen, wobei mindestens ein Block
mehr als 1 Höheninformationen beinhaltet. Es wird als Zellen typ 3 geschrieben, falls ein Block keine info beinhaltet 0 für den block typ, falls informationen vorhanden 1 für block typ und höheninformationen*(Z,NSWE)

Soweit dachte ich auch das ich das Komprimieren hinbekommen habe, nur beim lesen
der Höheninformations Dateien bekomme ich nicht erwartete Werte. Ich wäre sehr
dankbar wenn jemand helfen könnte und sich das anschauen könnte.

Das einlesen von den reinen Höheninformationen ist hier nicht das Problem, da ich von
diesen Problemlos Bitmaps mit Akuraten Höheninformtionen erstellen kann.

Programm für die convertierung der reinen Höheninformationsdaten:
BuildZoneConv.h
C++:
#ifndef __BUILDZONECONV_H__
#define __BUILDZONECONV_H__

#include <fstream>

int main( int argc, char **argv );

bool ParseDump();
void NonOptimized();
void CellOptimized();
void RepeatOptimized();
void ReleaseMemory();
void BinWrite( std::ofstream &Out, char *Data, int Bytes );

#endif

BuildZoneConv.cpp
C++:
#include "BuildZoneConv.h"

#include "..\..\Utils\Graphic\bitmap_Image.h"

#include "..\geoshared.h"

#include <iostream>
#include <string>

#include <windows.h>

/*
 * CellOptimized:
 * One geo region has 256x256 cells, each cell got 8x8 blocks in it
 *
 * CELL_NULL:
 * All cell blocks have 0 layers, no data needed at all
 *
 * CELL_FLAT:
 * All cell blocks have 1 layer and all Z values are the same, one Z value required to save
 *
 * CELL_MULTI:
 * Cell blocks have either 0 layers or 1 layer, at least 1 block with 1 layer, all 1 layer cell blocks have it's own Z value, each 1 layer block needs Z and NSWE saved
 *
 * CELL_LAYER:
 * Cell blocks have either 0 layers or more, at least 1 block with more than 1 layer, all cell blocks with layers greater 0 needs Layers*(Z,NSWE) saved
 * 
 */

Block *g_Blocks[ REGION_BLOCKS ];

std::string g_Region;
int g_MaxLayers = 0;

int main( int argc, char **argv ) {
    if ( argc < 2 ) {
        std::cout << "Usage: " << argv[ 0 ] << " <REGION>" << std::endl;
        getchar();
        return 1;
    }

    g_Region = argv[ 1 ];
    // initialize array with 0 values so cleanup goes well
    memset( g_Blocks, 0, REGION_BLOCKS );

    // parse the client geometry data into g_Blocks and generate bmp's for each layer
    if ( !ParseDump() ) {
        ReleaseMemory();
        return 1;
    }

    // generate geodata in non optimized format
    NonOptimized();
    // generate geodata in cell optimized format
    CellOptimized();
    // TODO: Implement generation of repeat optimization
    RepeatOptimized();
    std::cout << "Press [ENTER] to quit..." << std::endl;
    getchar();
}

bool ParseDump() {
    std::cout << "-= Parse dump =-" << std::endl;

    std::string GeoTextName = g_Region;
    std::ifstream GeoText;

    GeoTextName += ".txt";
    std::cout << "FILE: " << GeoTextName << "..." << std::endl;
    GeoText.open( GeoTextName.c_str() );

    if ( !GeoText.is_open() ) {
        std::cout << "ERROR: couldn't open file for reading!" << std::endl;
        return false;
    }

    std::string GeoLine = "";

    //Format: [x,y]layers(layer0_z:layer0_NSWE)....(layerN_z:layerN_NSWE)

    int Empty = 0;
    int X = 0;
    int Y = 0;
    int Offset = 0;

    while ( std::getline( GeoText, GeoLine ) ) {
        // Data in the dumped client files are lines starting with [
        if ( GeoLine.length() > 0 && GeoLine[ 0 ] == '[' ) {
            std::string::size_type Pos = 1;

            // X
            for ( std::string::size_type i = Pos;i < GeoLine.length();++ i ) {
                if ( GeoLine[ i ] == ',' ) {
                    X = atoi( GeoLine.substr( Pos, i - Pos ).c_str() );
                    Pos = i + 1;
                    break;
                }
            }

            // Y
            for ( std::string::size_type i = Pos;i < GeoLine.length();++ i ) {
                if ( GeoLine[ i ] == ']' ) {
                    Y = atoi( GeoLine.substr( Pos, i - Pos ).c_str() );
                    Pos = i + 1;
                    break;
                }
            }

            Offset = Y + X * REGION_BLOCKS_Y;

            // Layers, if 0 it's a null block
            if ( GeoLine[ Pos ] == '0' ) {
                ++ Empty;
                g_Blocks[ Offset ] = 0;
                continue;
            }

            // More than one layer, create a new block
            g_Blocks[ Offset ] = new Block;

            // Layers
            for ( std::string::size_type i = Pos;i < GeoLine.length();++ i ) {
                if ( GeoLine[ i ] == '(' ) {
                    g_Blocks[ Offset ]->Layers = atoi( GeoLine.substr( Pos, i - Pos ).c_str() );

                    if ( g_Blocks[ Offset ]->Layers > g_MaxLayers ) {
                        g_MaxLayers = g_Blocks[ Offset ]->Layers;
                    }

                    g_Blocks[ Offset ]->Z = new short[ g_Blocks[ Offset ]->Layers ];
                    g_Blocks[ Offset ]->NSWE = new char[ g_Blocks[ Offset ]->Layers ];
                    Pos = i + 1;
                    break;
                }
            }

            // Z and movement data Layers times
            for ( char c = 0;c < g_Blocks[ Offset ]->Layers;++ c ) {
                // Z
                for ( std::string::size_type i = Pos;i < GeoLine.length();++ i ) {
                    if ( GeoLine[ i ] == ':' ) {
                        g_Blocks[ Offset ]->Z[ c ] = atoi( GeoLine.substr( Pos, i - Pos ).c_str() );
                        Pos = i + 1;
                        break;
                    }
                }

                // Movement
                for ( std::string::size_type i = Pos;i < GeoLine.length();++ i ) {
                    if ( GeoLine[ i ] == ')' ) {
                        g_Blocks[ Offset ]->NSWE[ c ] = 0;

                        std::string NSWE = GeoLine.substr( Pos, i - Pos ).c_str();

                        // It's possible to come into this block from north
                        if ( NSWE[ 0 ] == '1' ) {
                            g_Blocks[ Offset ]->NSWE[ c ] |= NORTH;
                        }

                        // It's possible to come into this block from south
                        if ( NSWE[ 1 ] == '1' ) {
                            g_Blocks[ Offset ]->NSWE[ c ] |= SOUTH;
                        }

                        // It's possible to come into this block from west
                        if ( NSWE[ 2 ] == '1' ) {
                            g_Blocks[ Offset ]->NSWE[ c ] |= WEST;
                        }

                        // It's possible to come into this block from east
                        if ( NSWE[ 3 ] == '1' ) {
                            g_Blocks[ Offset ]->NSWE[ c ] |= EAST;
                        }

                        Pos = i + 2;
                        break;
                    }
                }
            }
        }
    }

    for ( int Layer = 0;Layer < g_MaxLayers;++ Layer ) {
        std::string FileName = "bmp\\(";
        FileName += g_Region;
        FileName += ")_";
        FileName += itoa( Layer, new char[ 11 ], 10 );
        std::string FileNameGray = FileName;
        FileNameGray += "_gray.bmp";
        FileName += ".bmp";

        bitmapImage b( REGION_BLOCKS_X, REGION_BLOCKS_Y ); // create a bitmap
        bitmapImage b_gray( REGION_BLOCKS_X, REGION_BLOCKS_Y ); // create a bitmap
 
        // loop through all of its pixels
        for (int BlockX=0;BlockX<REGION_BLOCKS_X;BlockX++) {
            for (int BlockY=0;BlockY<REGION_BLOCKS_Y;BlockY++) {
                Offset = BlockY + BlockX * REGION_BLOCKS_Y;

                if ( g_Blocks[ Offset ] == 0 || Layer > g_Blocks[ Offset ]->Layers - 1 ) {
                    b.setPixel( BlockX, BlockY, 0 );
                    b_gray.setPixel( BlockX, BlockY, 0 );
                } else {
                    int Val = ( g_Blocks[ Offset ]->Z[ Layer ] + 32768 ) / 256;
                    b_gray.setPixelRGB( BlockX, BlockY, Val, Val, Val );
                    b.setPixel( BlockX, BlockY, g_Blocks[ Offset ]->Z[ Layer ] + 32768 );
                }
            }
        }

        // save the bitmap to a file using a bit depth of 16
        b_gray.saveToBitmapFile( FileNameGray.c_str(), 16 );
        b.saveToBitmapFile( FileName.c_str(), 16 );
    }

    std::cout << "MaxLayers: " << g_MaxLayers << std::endl;
    std::cout << "Empty blocks: " << Empty << std::endl;
    return true;
}

void NonOptimized() {
    std::cout << "-= Non optimized output =-" << std::endl;

    std::string GeoName = g_Region;
    std::ofstream Geo;

    GeoName += "(NO).geo";
    std::cout << "FILE: " << GeoName << "..." << std::endl;
    Geo.open( GeoName.c_str() );

    if ( !Geo.is_open() ) {
        std::cout << "ERROR: couldn't open file for writing!" << std::endl;
        return;
    }

    // write geodata format byte at the start of the file
    BinWrite( Geo, ( char* )&GEOTYPE_NONOPTIMIZED, sizeof ( GEOTYPE_NONOPTIMIZED ) );

    // Write geodata
    for ( int i = 0;i < REGION_BLOCKS;++ i ) {
        if ( g_Blocks[ i ] == 0 ) {
            char b = 0;
            BinWrite( Geo, ( char* )&b, 1 );
            continue;
        }

        BinWrite( Geo, ( char* )&g_Blocks[ i ]->Layers, sizeof ( g_Blocks[ i ]->Layers ) );

        for ( char c = 0;c < g_Blocks[ i ]->Layers;++ c ) {
            BinWrite( Geo, ( char* )&g_Blocks[ i ]->Z[ c ], sizeof ( g_Blocks[ i ]->Z[ c ] ) );
            BinWrite( Geo, ( char* )&g_Blocks[ i ]->NSWE[ c ], sizeof( g_Blocks[ i ]->NSWE[ c ] ) );
        }
    }
}

// used for CellOptimized
Block *Cells[ REGION_CELLS ][ CELL_BLOCKS ];
char CellTypes[ REGION_CELLS ];

void CellOptimized() {
    std::cout << "-= Cell optimized output =-" << std::endl;
    std::cout << "OPTIMIZE: blocks into cells..." << std::endl;

    // Pack blocks into cells
    for ( int xC = 0;xC < REGION_CELLS_X;++ xC ) {
        for ( int yC = 0;yC < REGION_CELLS_Y;++ yC ) {
            // Cell offset
            int OffsetC = xC + yC * REGION_CELLS_X;

            for ( int xB = 0;xB < CELL_BLOCKS_X;++ xB ) {
                for ( int yB = 0;yB < CELL_BLOCKS_Y;++ yB ) {
                    // Block offset in cell
                    int OffsetB = xB + yB * CELL_BLOCKS_X;
                    // Region coordinates
                    int xR = xB + xC * CELL_BLOCKS_X;
                    int yR = yB + yC * CELL_BLOCKS_Y;
                    // Block offset in region
                    int OffsetR = xR + yR * REGION_BLOCKS_X;

                    Cells[ OffsetC ][ OffsetB ] = g_Blocks[ OffsetR ];
                }
            }
        }
    }

    int NullCells = 0;
    int FlatCells = 0;
    int MultiCells = 0;
    int LayerCells = 0;

    std::cout << "OPTIMIZE: Determine cell types..." << std::endl;

    // Determine cell types
    for ( int OffsetC = 0;OffsetC < REGION_CELLS;++ OffsetC ) {
        int Layers = 0;
        int Z = 0;
        bool CanBeFlat = true;

        for ( int OffsetB = 0;OffsetB < CELL_BLOCKS;++ OffsetB ) {
            if ( Cells[ OffsetC ][ OffsetB ] == 0 ) {
                // can't be flat anymore
                CanBeFlat = false;
                continue;
            }

            if ( Cells[ OffsetC ][ OffsetB ]->Layers > Layers ) {
                Layers = Cells[ OffsetC ][ OffsetB ]->Layers;

                if ( Layers > 1 ) {
                    // more than one layer can't be flat
                    CanBeFlat = false;
                }
            }

            if ( CanBeFlat && Cells[ OffsetC ][ OffsetB ]->Z[ 0 ] > Z && OffsetB > 0 ) {
                // cell with different Z values can't be flat
                CanBeFlat = false;
            }
        }

        if ( Layers == 0 ) {
            ++ NullCells;
            CellTypes[ OffsetC ] = CELL_NULL;
        } else if ( Layers == 1 && CanBeFlat ) {
            ++ FlatCells;
            CellTypes[ OffsetC ] = CELL_FLAT;
        } else if ( Layers == 1 ) {
            ++ MultiCells;
            CellTypes[ OffsetC ] = CELL_MULTI;
        } else {
            ++ LayerCells;
            CellTypes[ OffsetC ] = CELL_LAYER;
        }
    }

    std::cout << "OPTIMIZE: NullCells " << NullCells << std::endl;
    std::cout << "OPTIMIZE: FlatCells " << FlatCells << std::endl;
    std::cout << "OPTIMIZE: MultiCells " << MultiCells << std::endl;
    std::cout << "OPTIMIZE: LayerCells " << LayerCells << std::endl;

    std::string GeoName = g_Region;
    std::ofstream Geo;

    GeoName += "(CO).geo";
    std::cout << "FILE: " << GeoName << "..." << std::endl;
    Geo.open( GeoName.c_str() );

    if ( !Geo.is_open() ) {
        std::cout << "ERROR: couldn't open file for writing!" << std::endl;
    }

    // write geodata format byte at the start of the file
    BinWrite( Geo, ( char* )&GEOTYPE_CELLOPTIMIZED, sizeof ( GEOTYPE_CELLOPTIMIZED ) );

    for ( int OffsetC = 0;OffsetC < REGION_CELLS;++ OffsetC ) {
        BinWrite( Geo, ( char* )&CellTypes[ OffsetC ], sizeof ( CellTypes[ OffsetC ] ) );

        if ( CellTypes[ OffsetC ] == CELL_FLAT ) {
            // flat don't need NSWE data
            BinWrite( Geo, ( char* )&Cells[ OffsetC ][ 0 ]->Z[ 0 ], sizeof ( Cells[ OffsetC ][ 0 ]->Z[ 0 ] ) );
//            BinWrite( Geo, ( char* )&Cells[ OffsetC ][ 0 ]->NSWE[ 0 ], sizeof ( Cells[ OffsetC ][ 0 ]->NSWE[ 0 ] ) );
        } else if ( CellTypes[ OffsetC ] == CELL_MULTI ) {
            for ( int OffsetB = 0;OffsetB < CELL_BLOCKS;++ OffsetB ) {
                if ( Cells[ OffsetC ][ OffsetB ] == 0 ) {
                    BinWrite( Geo, ( char* )&BLOCK_NULL, sizeof ( BLOCK_NULL ) );
                    continue;
                }

                BinWrite( Geo, ( char* )&BLOCK_DATA, sizeof ( BLOCK_DATA ) );
                BinWrite( Geo, ( char* )&Cells[ OffsetC ][ OffsetB ]->Z[ 0 ], sizeof ( Cells[ OffsetC ][ OffsetB ]->Z[ 0 ] ) );
                BinWrite( Geo, ( char* )&Cells[ OffsetC ][ OffsetB ]->NSWE[ 0 ], sizeof ( Cells[ OffsetC ][ OffsetB ]->NSWE[ 0 ] ) );
            }
        } else if ( CellTypes[ OffsetC ] == CELL_LAYER ) {
            for ( int OffsetB = 0;OffsetB < CELL_BLOCKS;++ OffsetB ) {
                if ( Cells[ OffsetC ][ OffsetB ] == 0 ) {
                    BinWrite( Geo, ( char* )&BLOCK_NULL, sizeof ( BLOCK_NULL ) );
                    continue;
                }

                BinWrite( Geo, ( char* )&BLOCK_DATA, sizeof ( BLOCK_DATA ) );
                BinWrite( Geo, ( char* )&Cells[ OffsetC ][ OffsetB ]->Layers, sizeof ( Cells[ OffsetC ][ OffsetB ]->Layers ) );

                for ( int Layer = 0;Layer < Cells[ OffsetC ][ OffsetB ]->Layers;++ Layer ) {
                    BinWrite( Geo, ( char* )&Cells[ OffsetC ][ OffsetB ]->Z[ Layer ], sizeof ( Cells[ OffsetC ][ OffsetB ]->Z[ Layer ] ) );
                    BinWrite( Geo, ( char* )&Cells[ OffsetC ][ OffsetB ]->NSWE[ Layer ], sizeof ( Cells[ OffsetC ][ OffsetB ]->NSWE[ Layer ] ) );
                }
            }
        }
    }
}

void RepeatOptimized() {
}

void ReleaseMemory() {
    for ( int i = 0;i < REGION_BLOCKS;++ i ) {
        if ( g_Blocks[ i ] != NULL ) {
            delete[] g_Blocks[ i ]->Z;
            delete[] g_Blocks[ i ]->NSWE;
            delete g_Blocks[ i ];
        }
    }
}

void BinWrite( std::ofstream &Out, char *Data, int Bytes ) {
    Out.write( Data, Bytes );
}


Programm zum auslesen des CellOptimized outputs:
GeoEngine.h
C++:
#ifndef __GEOENGINE_H__
#define __GEOENGINE_H__

#include "..\geoshared.h"

#if !defined(WIN32) && !defined(__linux__)

#endif

#ifdef __cplusplus
#    define EXTERN_C extern "C"
#else
#    define EXTERN_C
#endif

#ifdef WIN32
#    ifdef GEOENGINE_EXPORTS
#        define GEOENGINE_API __declspec ( dllexport )
#    else
#        define GEOENGINE_API __declspec ( dllimport )
#    endif
#else
#    define GEOENGINE_API
#endif

#define RLE_OK    0
#define RLE_OPEN_FILE 1
#define RLE_MAP 2
#define RLE_FORMAT 3
#define RLE_MEMORY 4

EXTERN_C GEOENGINE_API void GeoEngine_Init();
EXTERN_C GEOENGINE_API void GeoEngine_DeInit();
EXTERN_C GEOENGINE_API long GeoEngine_Region( const char *RegionFile, char RegionX, char RegionY );

#endif

GeoEngine.cpp
C++:
#include "GeoEngine.h"

#include <sys/stat.h>

#include <iostream>

#ifdef WIN32
#    include <windows.h>
#else
#endif

typedef struct {
    Block *Blocks[ 64 ];
} Cell;

Cell *g_Cells[ WORLD_CELLS ];

#ifdef WIN32
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) {
    return TRUE;
}
#endif

void GeoEngine_Init() {
    memset( g_Cells, 0, WORLD_CELLS );
}

void GeoEngine_DeInit() {
}

void BinRead( char *Dest, const char *&DataPtr, int Bytes );

long GeoEngine_Region( const char *RegionFile, char RegionX, char RegionY ) {
#ifdef WIN32
    HANDLE hFile = CreateFileA( RegionFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );

    if ( hFile == INVALID_HANDLE_VALUE ) {
        return RLE_OPEN_FILE;
    }
#else
    int fd = open( RegionFile, O_RDONLY );

    if ( fd == -1 ) {
        return RLE_OPEN_FILE;
    }
#endif

    struct stat fstat;
    stat( RegionFile, &fstat );

#ifdef WIN32
    HANDLE hMapFile = CreateFileMappingA( hFile, NULL, PAGE_READONLY, 0, fstat.st_size, RegionFile );

    if ( hMapFile == 0 ) {
        CloseHandle( hFile );
        return RLE_MAP;
    }

    const char *MapPtr = ( const char* )MapViewOfFile( hMapFile, FILE_MAP_READ, 0, 0, fstat.st_size );
#else
    const char *MapPtr = mmap( 0, fstat.st_size, PROT_READ, MAP_SHARED, fd, 0 );
#endif

    if ( MapPtr == 0 ) {
#ifdef WIN32
        CloseHandle( hMapFile );
        CloseHandle( hFile );
#else
        close( fd );
#endif
        return RLE_MAP;
    }

    const char *DataPtr = MapPtr;
    char GeoType = 0;
    BinRead( &GeoType, DataPtr, 1 );

    if ( GeoType != GEOTYPE_CELLOPTIMIZED ) {
#ifdef WIN32
        UnmapViewOfFile( MapPtr );
        CloseHandle( hMapFile );
        CloseHandle( hFile );
#else
        close( fd );
#endif
        return RLE_FORMAT;
    }

    short RegionOffset = RegionX + RegionY * WORLD_REGIONS_X;

    for ( long i = 0;i < REGION_CELLS;++ i ) {
        std::cout << "CellOffset: " << i << std::endl;
        char CellType = 0;
        BinRead( &CellType, DataPtr, 1 );

        unsigned long CellX = i % REGION_CELLS_X;
        unsigned long CellY = ( i - CellX ) / REGION_CELLS_X;
        unsigned long WorldCellX = CellX + RegionX * REGION_CELLS_X;
        unsigned long WorldCellY = CellY + RegionY * REGION_CELLS_Y;
        unsigned long WorldCellOffset = WorldCellX + WorldCellY * WORLD_CELLS_X;

        Block *B  = NULL;

        switch ( CellType ) {
        case CELL_NULL:
            break;
        case CELL_FLAT:
            g_Cells[ WorldCellOffset ] = new Cell;
            B = new Block;
            B->Layers = 1;
            B->Z = new short[ 1 ];
            BinRead( ( char* )&B->Z[ 0 ], DataPtr, sizeof ( B->Z[ 0 ] ) );
            B->NSWE = new char[ 1 ];
            B->NSWE[ 0 ] = NORTH | SOUTH | WEST | EAST;
            //B->NSWE[ 0 ] = *DataPtr;
            //DataPtr += 1;

            for ( unsigned char c = 0;c < CELL_BLOCKS;++ c ) {
                g_Cells[ WorldCellOffset ]->Blocks[ c ] = B;
            }

            break;
        case CELL_MULTI:
            g_Cells[ WorldCellOffset ] = new Cell;

            for ( unsigned char c = 0;c < CELL_BLOCKS;++ c ) {
                char BlockType = 0;
                BinRead( &BlockType, DataPtr, 1 );

                switch ( BlockType ) {
                case BLOCK_NULL:
                    g_Cells[ WorldCellOffset ]->Blocks[ c ] = 0;
                    break;
                case BLOCK_DATA:
                    g_Cells[ WorldCellOffset ]->Blocks[ c ] = new Block;
                    g_Cells[ WorldCellOffset ]->Blocks[ c ]->Layers = 1;
                    g_Cells[ WorldCellOffset ]->Blocks[ c ]->Z = new short[ 1 ];
                    g_Cells[ WorldCellOffset ]->Blocks[ c ]->NSWE = new char[ 1 ];
                    BinRead( ( char* )&g_Cells[ WorldCellOffset ]->Blocks[ c ]->Z[ 0 ], DataPtr, sizeof ( g_Cells[ WorldCellOffset ]->Blocks[ c ]->Z[ 0 ] ) );
                    BinRead( &g_Cells[ WorldCellOffset ]->Blocks[ c ]->NSWE[ 0 ], DataPtr, sizeof ( g_Cells[ WorldCellOffset ]->Blocks[ c ]->NSWE[ 0 ] ) );
                    break;
                default:
                    std::cout << "Layered cell, unknown block type: " << ( int )BlockType << std::endl;
#ifdef WIN32
                    UnmapViewOfFile( MapPtr );
                    CloseHandle( hMapFile );
                    CloseHandle( hFile );
#else
                    close( fd );
#endif
                    return RLE_FORMAT;
                    break;
                }
            }

            break;
        case CELL_LAYER:
            g_Cells[ WorldCellOffset ] = new Cell;

            for ( unsigned char c = 0;c < CELL_BLOCKS;++ c ) {
                char BlockType = 0;
                BinRead( &BlockType, DataPtr, 1 );

                switch ( BlockType ) {
                case BLOCK_NULL:
                    g_Cells[ WorldCellOffset ]->Blocks[ c ] = 0;
                    break;
                case BLOCK_DATA:
                    g_Cells[ WorldCellOffset ]->Blocks[ c ] = new Block;
                    BinRead( &g_Cells[ WorldCellOffset ]->Blocks[ c ]->Layers, DataPtr, sizeof ( g_Cells[ WorldCellOffset ]->Blocks[ c ]->Layers ) );
                    g_Cells[ WorldCellOffset ]->Blocks[ c ]->Z = new short[ g_Cells[ WorldCellOffset ]->Blocks[ c ]->Layers ];
                    g_Cells[ WorldCellOffset ]->Blocks[ c ]->NSWE = new char[ g_Cells[ WorldCellOffset ]->Blocks[ c ]->Layers ];

                    for ( unsigned char Layer = 0;Layer < g_Cells[ WorldCellOffset ]->Blocks[ c ]->Layers;++ Layer ) {
                        BinRead( ( char* )&g_Cells[ WorldCellOffset ]->Blocks[ c ]->Z[ Layer ], DataPtr, sizeof ( g_Cells[ WorldCellOffset ]->Blocks[ c ]->Z[ Layer ] ) );
                        BinRead( &g_Cells[ WorldCellOffset ]->Blocks[ c ]->NSWE[ Layer ], DataPtr, sizeof ( g_Cells[ WorldCellOffset ]->Blocks[ c ]->NSWE[ Layer ] ) );
                    }

                    break;
                default:
                    std::cout << "Layered cell, unknown block type: " << ( int )BlockType << std::endl;
#ifdef WIN32
                    UnmapViewOfFile( MapPtr );
                    CloseHandle( hMapFile );
                    CloseHandle( hFile );
#else
                    close( fd );
#endif
                    return RLE_FORMAT;
                }
            }

            break;
        default:
            std::cout << "Unknown cell type: " << ( int )CellType << std::endl;
#ifdef WIN32
            UnmapViewOfFile( MapPtr );
            CloseHandle( hMapFile );
            CloseHandle( hFile );
#else
            close( fd );
#endif
            return RLE_FORMAT;
        }
    }

#ifdef WIN32
    UnmapViewOfFile( MapPtr );
    CloseHandle( hMapFile );
    CloseHandle( hFile );
#else
    close( fd );
#endif
    return RLE_OK;
}

void BinRead( char *Dest, const char *&DataPtr, int Bytes ) {
    memcpy( Dest, DataPtr, Bytes );
    DataPtr += Bytes;
}

Hier noch der shared Header:
geoshared.h
C++:
#ifndef __GEOSHARED_H__
#define __GEOSHARED_H__

/******************************
 * CELL
 */
const unsigned long CELL_BLOCKS_X    = 8;
const unsigned long CELL_BLOCKS_Y    = 8;
const unsigned long CELL_BLOCKS        = CELL_BLOCKS_X * CELL_BLOCKS_Y;
/******************************/

/******************************
 * REGION
 */
const unsigned long REGION_CELLS_X    = 256;
const unsigned long REGION_CELLS_Y    = 256;
const unsigned long REGION_CELLS    = REGION_CELLS_X * REGION_CELLS_Y;

const unsigned long REGION_BLOCKS_X    = REGION_CELLS_X * CELL_BLOCKS_X;
const unsigned long REGION_BLOCKS_Y    = REGION_CELLS_Y * CELL_BLOCKS_Y;
const unsigned long REGION_BLOCKS    = REGION_BLOCKS_X * REGION_BLOCKS_Y;
/******************************/

/******************************
 * WORLD
 */
const unsigned long WORLD_REGIONS_X    = 32;
const unsigned long WORLD_REGIONS_Y    = 32;
const unsigned long WORLD_REGIONS    = WORLD_REGIONS_X * WORLD_REGIONS_Y;

const unsigned long WORLD_CELLS_X    = WORLD_REGIONS_X * REGION_CELLS_X;
const unsigned long WORLD_CELLS_Y    = WORLD_REGIONS_Y * REGION_CELLS_Y;
const unsigned long WORLD_CELLS        = WORLD_CELLS_X * WORLD_CELLS_Y;

const unsigned long WORLD_BLOCKS_X    = WORLD_REGIONS_X * REGION_BLOCKS_X;
const unsigned long WORLD_BLOCKS_Y    = WORLD_REGIONS_Y * REGION_BLOCKS_Y;
//const unsigned long WORLD_BLOCKS    = WORLD_BLOCKS_X * WORLD_BLOCKS_Y;
/******************************/

typedef struct {
    char Layers;
    short *Z;
    char *NSWE;
} Block;

/******************************
 * NSWE
 */
const char NORTH    = 1;
const char SOUTH    = 1 << 1;
const char WEST        = 1 << 2;
const char EAST        = 1 << 3;
/******************************/

/******************************
 * CELL TYPES
 */
const char CELL_NULL    = 0;
const char CELL_FLAT    = 1;
const char CELL_MULTI    = 2;
const char CELL_LAYER    = 3;
/******************************/

/******************************
 * BLOCK TYPE
 */
const char BLOCK_NULL    = 0;
const char BLOCK_DATA    = 1;
/******************************/

/******************************
 * GEODATA FORMAT
 */
const char GEOTYPE_NONOPTIMIZED        = 0;
const char GEOTYPE_CELLOPTIMIZED    = 1;
const char GEOTYPE_REPEATOPTIMIZED    = 2;
/******************************/

#endif

Das wäre alles an SourceCode. Ich verzweifle solangsam daran, da ich den Code
dutzende male überprüft habe, aber aufs Verrecken keinen Fehler finden kann.

GeoEngine_Region() resultiert RLE_FORMAT, und sagt mir das ich ein unbekanten Block Typ habe.
Eine Testdatei lae ich gerade bei rapidshare rauf.

EDIT:
Test Landschaftsinfos: http://rapidshare.com/files/137829157/25_15.zip.html
.txt Datei in den Ordner von BuildZoneConv legen und einen Ordner bmp anlegen. Nun BuildZoneConv mit parameter
25_15 starten.


Best wishes
FBIagent
 
Zuletzt bearbeitet von einem Moderator:

deepthroat

Erfahrenes Mitglied
Hi.

Hab's mir mal angeschaut (nachdem ich die Fehler entfernt und es kompiliert bekommen habe...).

Das Problem ist, das du die Daten nicht richtig schreibst. Mach's mal so:
C++:
Geo.open( GeoName.c_str(), std::ios::binary | std::ios::out );
Gruß
 

FBIagent

Erfahrenes Mitglied
Hi.

Hab's mir mal angeschaut (nachdem ich die Fehler entfernt und es kompiliert bekommen habe...).
Tut mir leid, ich habe die bitmapImage.h vergessen.

Das Problem ist, das du die Daten nicht richtig schreibst. Mach's mal so:
cpp Code:
  1. Geo.open( GeoName.c_str(), std::ios::binary | std::ios::eek:ut );

Gruß
Stimmt, das hatte ich vergessen, das ich in binary mode öffnen.
Nun läuft alles einwandfrei, danke.

Best wishes
FBIagent
 
Zuletzt bearbeitet:

Neue Beiträge