All pastes #1821115 Raw Copy code Copy link Edit

scr/mmap/GridMapManager.cpp

public cpp v1 · immutable
#1821115 ·published 2010-03-03 12:42 UTC
rendered paste body
#include "GridMapManager.h"namespace VMAP{    GridMap::GridMap()    {        m_flags = 0;        // Area data        m_gridArea = 0;        m_area_map = NULL;        // Height level data        m_gridHeight = -100000.0f;        m_gridGetHeight = &GridMap::getHeightFromFlat;        m_V9 = NULL;        m_V8 = NULL;        // Liquid data        m_liquidType    = 0;        m_liquid_offX   = 0;        m_liquid_offY   = 0;        m_liquid_width  = 0;        m_liquid_height = 0;        m_liquidLevel = -100000.0f;        m_liquid_type = NULL;        m_liquid_map  = NULL;    }    GridMap::~GridMap()    {        unloadData();    }    bool GridMap::loadAreaData(FILE *in, uint32 offset, uint32 /*size*/)    {        map_areaHeader header;        fseek(in, offset, SEEK_SET);        fread(&header, sizeof(header), 1, in);        if (header.fourcc != *((uint32 const*)(MAP_AREA_MAGIC)))            return false;        m_gridArea = header.gridArea;        if (!(header.flags & MAP_AREA_NO_AREA))        {            m_area_map = new uint16 [16*16];            fread(m_area_map, sizeof(uint16), 16*16, in);        }        return true;    }    bool  GridMap::loadHeightData(FILE *in, uint32 offset, uint32 /*size*/)    {        map_heightHeader header;        fseek(in, offset, SEEK_SET);        fread(&header, sizeof(header), 1, in);        if (header.fourcc != *((uint32 const*)(MAP_HEIGHT_MAGIC)))            return false;        m_gridHeight = header.gridHeight;        if (!(header.flags & MAP_HEIGHT_NO_HEIGHT))        {            if ((header.flags & MAP_HEIGHT_AS_INT16))            {                m_uint16_V9 = new uint16 [129*129];                m_uint16_V8 = new uint16 [128*128];                fread(m_uint16_V9, sizeof(uint16), 129*129, in);                fread(m_uint16_V8, sizeof(uint16), 128*128, in);                m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 65535;                m_gridGetHeight = &GridMap::getHeightFromUint16;            }            else if ((header.flags & MAP_HEIGHT_AS_INT8))            {                m_uint8_V9 = new uint8 [129*129];                m_uint8_V8 = new uint8 [128*128];                fread(m_uint8_V9, sizeof(uint8), 129*129, in);                fread(m_uint8_V8, sizeof(uint8), 128*128, in);                m_gridIntHeightMultiplier = (header.gridMaxHeight - header.gridHeight) / 255;                m_gridGetHeight = &GridMap::getHeightFromUint8;            }            else            {                m_V9 = new float [129*129];                m_V8 = new float [128*128];                fread(m_V9, sizeof(float), 129*129, in);                fread(m_V8, sizeof(float), 128*128, in);                m_gridGetHeight = &GridMap::getHeightFromFloat;            }        }        else            m_gridGetHeight = &GridMap::getHeightFromFlat;        return true;    }    bool  GridMap::loadLiquidData(FILE *in, uint32 offset, uint32 /*size*/)    {        map_liquidHeader header;        fseek(in, offset, SEEK_SET);        fread(&header, sizeof(header), 1, in);        if (header.fourcc != *((uint32 const*)(MAP_LIQUID_MAGIC)))            return false;        m_liquidType   = header.liquidType;        m_liquid_offX  = header.offsetX;        m_liquid_offY  = header.offsetY;        m_liquid_width = header.width;        m_liquid_height= header.height;        m_liquidLevel  = header.liquidLevel;        if (!(header.flags & MAP_LIQUID_NO_TYPE))        {            m_liquid_type = new uint8 [16*16];            fread(m_liquid_type, sizeof(uint8), 16*16, in);        }        if (!(header.flags & MAP_LIQUID_NO_HEIGHT))        {            m_liquid_map = new float [m_liquid_width*m_liquid_height];            fread(m_liquid_map, sizeof(float), m_liquid_width*m_liquid_height, in);        }        return true;    }    float  GridMap::getHeightFromFlat(float /*x*/, float /*y*/) const    {        return m_gridHeight;    }    float  GridMap::getHeightFromFloat(float x, float y) const    {        if (!m_V8 || !m_V9)            return m_gridHeight;        x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);        y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);        int x_int = (int)x;        int y_int = (int)y;        x -= x_int;        y -= y_int;        x_int&=(MAP_RESOLUTION - 1);        y_int&=(MAP_RESOLUTION - 1);        // Height stored as: h5 - its v8 grid, h1-h4 - its v9 grid        // +--------------> X        // | h1-------h2     Coordinates is:        // | | \  1  / |     h1 0,0        // | |  \   /  |     h2 0,1        // | | 2  h5 3 |     h3 1,0        // | |  /   \  |     h4 1,1        // | | /  4  \ |     h5 1/2,1/2        // | h3-------h4        // V Y        // For find height need        // 1 - detect triangle        // 2 - solve linear equation from triangle points        // Calculate coefficients for solve h = a*x + b*y + c        float a,b,c;        // Select triangle:        if (x+y < 1)        {            if (x > y)            {                // 1 triangle (h1, h2, h5 points)                float h1 = m_V9[(x_int  )*129 + y_int];                float h2 = m_V9[(x_int+1)*129 + y_int];                float h5 = 2 * m_V8[x_int*128 + y_int];                a = h2-h1;                b = h5-h1-h2;                c = h1;            }            else            {                // 2 triangle (h1, h3, h5 points)                float h1 = m_V9[x_int*129 + y_int  ];                float h3 = m_V9[x_int*129 + y_int+1];                float h5 = 2 * m_V8[x_int*128 + y_int];                a = h5 - h1 - h3;                b = h3 - h1;                c = h1;            }        }        else        {            if (x > y)            {                // 3 triangle (h2, h4, h5 points)                float h2 = m_V9[(x_int+1)*129 + y_int  ];                float h4 = m_V9[(x_int+1)*129 + y_int+1];                float h5 = 2 * m_V8[x_int*128 + y_int];                a = h2 + h4 - h5;                b = h4 - h2;                c = h5 - h4;            }            else            {                // 4 triangle (h3, h4, h5 points)                float h3 = m_V9[(x_int  )*129 + y_int+1];                float h4 = m_V9[(x_int+1)*129 + y_int+1];                float h5 = 2 * m_V8[x_int*128 + y_int];                a = h4 - h3;                b = h3 + h4 - h5;                c = h5 - h4;            }        }        // Calculate height        return a * x + b * y + c;    }    float  GridMap::getHeightFromUint8(float x, float y) const    {        if (!m_uint8_V8 || !m_uint8_V9)            return m_gridHeight;        x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);        y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);        int x_int = (int)x;        int y_int = (int)y;        x -= x_int;        y -= y_int;        x_int&=(MAP_RESOLUTION - 1);        y_int&=(MAP_RESOLUTION - 1);        int32 a, b, c;        uint8 *V9_h1_ptr = &m_uint8_V9[x_int*128 + x_int + y_int];        if (x+y < 1)        {            if (x > y)            {                // 1 triangle (h1, h2, h5 points)                int32 h1 = V9_h1_ptr[  0];                int32 h2 = V9_h1_ptr[129];                int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];                a = h2-h1;                b = h5-h1-h2;                c = h1;            }            else            {                // 2 triangle (h1, h3, h5 points)                int32 h1 = V9_h1_ptr[0];                int32 h3 = V9_h1_ptr[1];                int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];                a = h5 - h1 - h3;                b = h3 - h1;                c = h1;            }        }        else        {            if (x > y)            {                // 3 triangle (h2, h4, h5 points)                int32 h2 = V9_h1_ptr[129];                int32 h4 = V9_h1_ptr[130];                int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];                a = h2 + h4 - h5;                b = h4 - h2;                c = h5 - h4;            }            else            {                // 4 triangle (h3, h4, h5 points)                int32 h3 = V9_h1_ptr[  1];                int32 h4 = V9_h1_ptr[130];                int32 h5 = 2 * m_uint8_V8[x_int*128 + y_int];                a = h4 - h3;                b = h3 + h4 - h5;                c = h5 - h4;            }        }        // Calculate height        return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;    }    float  GridMap::getHeightFromUint16(float x, float y) const    {        if (!m_uint16_V8 || !m_uint16_V9)            return m_gridHeight;        x = MAP_RESOLUTION * (32 - x/SIZE_OF_GRIDS);        y = MAP_RESOLUTION * (32 - y/SIZE_OF_GRIDS);        int x_int = (int)x;        int y_int = (int)y;        x -= x_int;        y -= y_int;        x_int&=(MAP_RESOLUTION - 1);        y_int&=(MAP_RESOLUTION - 1);        int32 a, b, c;        uint16 *V9_h1_ptr = &m_uint16_V9[x_int*128 + x_int + y_int];        if (x+y < 1)        {            if (x > y)            {                // 1 triangle (h1, h2, h5 points)                int32 h1 = V9_h1_ptr[  0];                int32 h2 = V9_h1_ptr[129];                int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];                a = h2-h1;                b = h5-h1-h2;                c = h1;            }            else            {                // 2 triangle (h1, h3, h5 points)                int32 h1 = V9_h1_ptr[0];                int32 h3 = V9_h1_ptr[1];                int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];                a = h5 - h1 - h3;                b = h3 - h1;                c = h1;            }        }        else        {            if (x > y)            {                // 3 triangle (h2, h4, h5 points)                int32 h2 = V9_h1_ptr[129];                int32 h4 = V9_h1_ptr[130];                int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];                a = h2 + h4 - h5;                b = h4 - h2;                c = h5 - h4;            }            else            {                // 4 triangle (h3, h4, h5 points)                int32 h3 = V9_h1_ptr[  1];                int32 h4 = V9_h1_ptr[130];                int32 h5 = 2 * m_uint16_V8[x_int*128 + y_int];                a = h4 - h3;                b = h3 + h4 - h5;                c = h5 - h4;            }        }        // Calculate height        return (float)((a * x) + (b * y) + c)*m_gridIntHeightMultiplier + m_gridHeight;    }    bool GridMap::loadData(char *filename)    {        // Unload old data if exist        unloadData();        map_fileheader header;        // Not return error if file not found        FILE *in = fopen(filename, "rb");        if (!in)            return true;        fread(&header, sizeof(header),1,in);        if (header.mapMagic     == *((uint32 const*)(MAP_MAGIC)) &&            header.versionMagic == *((uint32 const*)(MAP_VERSION_MAGIC)) ) // ||            //!IsAcceptableClientBuild(header.buildMagic))        {            // loadup area data            if (header.areaMapOffset && !loadAreaData(in, header.areaMapOffset, header.areaMapSize))            {                printf("Error loading map area data\n");                fclose(in);                return false;            }            // loadup height data            if (header.heightMapOffset && !loadHeightData(in, header.heightMapOffset, header.heightMapSize))            {                printf("Error loading map height data\n");                fclose(in);                return false;            }            // loadup liquid data            if (header.liquidMapOffset && !loadLiquidData(in, header.liquidMapOffset, header.liquidMapSize))            {                printf("Error loading map liquids data\n");                fclose(in);                return false;            }            fclose(in);            printf("Map file %s loaded.\n",filename);            return true;        }        printf("Map file '%s' is non-compatible version (outdated?). Please, create new using ad.exe program.", filename);        fclose(in);        return false;    }    void GridMap::unloadData()    {        if (m_area_map) delete[] m_area_map;        if (m_V9) delete[] m_V9;        if (m_V8) delete[] m_V8;        if (m_liquid_type) delete[] m_liquid_type;        if (m_liquid_map) delete[] m_liquid_map;        m_area_map = NULL;        m_V9 = NULL;        m_V8 = NULL;        m_liquid_type = NULL;        m_liquid_map  = NULL;        m_gridGetHeight = &GridMap::getHeightFromFlat;    }  //================================================    GridMapManager::GridMapManager(const char* pBasePath, unsigned int pMapId)    {        iBasePath = std::string (pBasePath);        iMapId = pMapId;        for (unsigned int idx = 0; idx < MAX_NUMBER_OF_GRIDS; ++idx)        {            for (unsigned int j = 0; j < MAX_NUMBER_OF_GRIDS; ++j)            {                iGridMaps[idx][j] = NULL;                iMapExist[idx][j] = true;            }        }    }    //================================================    GridMapManager::~GridMapManager () { }    //================================================    bool GridMapManager::loadMap (int pX, int pY)    {        bool result = true;        if (!iGridMaps[pX][pY] && iMapExist[pX][pY])        {            result = false;            int len = 500;            char* tmp = new char[len];            sprintf (tmp, (iBasePath + "/maps/%03u%02u%02u.map").c_str (), iMapId, pX, pY);            // loading data            FILE *pf = fopen (tmp, "rb");            if (pf)            {                iGridMaps[pX][pY] = new GridMap();                if (!iGridMaps[pX][pY]->loadData(tmp))                {                    iMapExist[pX][pY] = false;                }            }            else                iMapExist[pX][pY] = false;            delete [] tmp;        }        return result;    }    //================================================    void GridMapManager::unloadMap (int pX, int pY)    {        if (!iGridMaps[pX][pY])        {            delete iGridMaps[pX][pY];            iGridMaps[pX][pY] = NULL;        }    }    //================================================    float GridMapManager::getHeight (float pX, float pY)    {        int gx, gy;        gx = (int) (32 - pX / SIZE_OF_GRIDS); //grid x        gy = (int) (32 - pY / SIZE_OF_GRIDS); //grid y        if (!iGridMaps[gx][gy]) //this map is not loaded            loadMap (gx, gy);        if (!iMapExist[gx][gy])            return -100000.0f;        return iGridMaps[gx][gy]->getHeight(pX,pY);    }    //================================================}