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); } //================================================}