Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- //----------------------------------------------------------
- //
- // SA-MP Multiplayer Modification For GTA:SA
- // Copyright 2004-2010 SA-MP Team
- //
- // Author: Kye 10 Jan 2010
- //
- //----------------------------------------------------------
- #include <stdio.h>
- #include <stdlib.h>
- #include <math.h>
- #include "MapAndreas.h"
- //----------------------------------------------------------
- CMapAndreas::CMapAndreas()
- {
- m_iOperatingMode = MAP_ANDREAS_MODE_NONE;
- m_pPointData = NULL;
- }
- //----------------------------------------------------------
- CMapAndreas::~CMapAndreas()
- {
- m_iOperatingMode = MAP_ANDREAS_MODE_NONE;
- if(m_pPointData) free(m_pPointData);
- m_pPointData = NULL;
- }
- //----------------------------------------------------------
- int CMapAndreas::Init(int iMode)
- {
- // check if already inited
- if(m_iOperatingMode != MAP_ANDREAS_MODE_NONE)
- return MAP_ANDREAS_ERROR_SUCCESS;
- if(iMode == MAP_ANDREAS_MODE_FULL)
- {
- // allocate the memory we need
- m_pPointData = (unsigned short *)calloc(MAP_ANDREAS_POINTS_FULL,sizeof(unsigned short));
- if(NULL == m_pPointData) return MAP_ANDREAS_ERROR_MEMORY;
- // load the file contents in to our point data buffer
- FILE *fileInput = fopen(MAP_ANDREAS_HMAP_FILE_FULL,"rb");
- if(NULL == fileInput) return MAP_ANDREAS_ERROR_DATA_FILES;
- /**
- * Старая версия (грузит пару секунд
- *
- for(int x=0;x<MAP_ANDREAS_POINTS_FULL;x++) {
- fread(&m_pPointData[x],1,sizeof(unsigned short),fileInput);
- }
- */
- // Новая версия - грузит меньше чем за секунду
- unsigned short points_line[6000];
- for(int x=0;x<MAP_ANDREAS_POINTS_FULL/6000;x++) {
- fread(&points_line,6000,sizeof(unsigned short),fileInput);
- for(int k=0; k<6000; k++){
- m_pPointData[x*6000+k] = points_line[k];
- }
- }
- fclose(fileInput);
- m_iOperatingMode = MAP_ANDREAS_MODE_FULL;
- m_gridSize = MAP_ANDREAS_GRID_FULL;
- return MAP_ANDREAS_ERROR_SUCCESS;
- } else
- if(iMode == MAP_ANDREAS_MODE_MINIMAL)
- {
- m_pPointData = (unsigned short *)calloc(MAP_ANDREAS_POINTS_MINIMAL,sizeof(unsigned short));
- if(NULL == m_pPointData) return MAP_ANDREAS_ERROR_MEMORY;
- FILE *fileInput = fopen(MAP_ANDREAS_HMAP_FILE_MINIMAL,"rb");
- if(NULL == fileInput) return MAP_ANDREAS_ERROR_DATA_FILES;
- for(int x=0;x<MAP_ANDREAS_POINTS_MINIMAL;x++) {
- fread(&m_pPointData[x],1,sizeof(unsigned short),fileInput);
- }
- fclose(fileInput);
- m_iOperatingMode = MAP_ANDREAS_MODE_MINIMAL;
- m_gridSize = MAP_ANDREAS_GRID_MINIMAL;
- return MAP_ANDREAS_ERROR_SUCCESS;
- } else
- if(iMode == MAP_ANDREAS_MODE_NOBUFFER)
- {
- m_iOperatingMode = MAP_ANDREAS_MODE_NOBUFFER;
- m_gridSize = MAP_ANDREAS_GRID_FULL;
- m_pPointData = (unsigned short *)calloc(1,sizeof(unsigned short));
- mapFile = fopen(MAP_ANDREAS_HMAP_FILE_FULL,"rb");
- if(NULL == mapFile) return MAP_ANDREAS_ERROR_DATA_FILES;
- return MAP_ANDREAS_ERROR_SUCCESS;
- }
- return MAP_ANDREAS_ERROR_FAILURE;
- }
- //----------------------------------------------------------
- float CMapAndreas::FindZ_For2DCoord(float X, float Y)
- {
- // check for a co-ord outside the map
- if(X < -2999.0f || X > 2999.0f || Y > 2999.0f || Y < -2999.0f) return 0.0f;
- // get row/col on 6000x6000 grid
- int iGridX = ((int)X) + 3000;
- int iGridY = (((int)Y) - 3000) * -1;
- int iDataPos;
- if(m_iOperatingMode == MAP_ANDREAS_MODE_FULL)
- {
- iDataPos = (iGridY * 6000) + iGridX; // for every Y, increment by the number of cols, add the col index.
- return (float)m_pPointData[iDataPos] / 100.0f; // the data is a float stored as ushort * 100
- } else
- if(m_iOperatingMode == MAP_ANDREAS_MODE_MINIMAL)
- {
- iDataPos = ((iGridY / 3) * 2000) + iGridX / 3; // skip every 2nd and 3rd line
- return (float)m_pPointData[iDataPos] / 100.0f;
- } else
- if(m_iOperatingMode == MAP_ANDREAS_MODE_NOBUFFER)
- {
- iDataPos = (iGridY * 6000) + iGridX;
- // Jump to the position in the file and read it
- fseek(mapFile, iDataPos * sizeof(unsigned short), SEEK_SET);
- fread(&m_pPointData[0], 1, sizeof(unsigned short), mapFile);
- return (float)m_pPointData[0] / 100.0f;
- }
- return 0.0f;
- }
- float CMapAndreas::GetAverageZ(float x, float y)
- {
- int whole[2];
- whole[0] = (int)floor(x);
- whole[1] = (int)floor(y);
- bool triangle;
- if((x - (float)whole[0]) + (y - (float)whole[1]) < 1.0){
- triangle = false;
- }else{
- triangle = true;
- }
- float floor_x = (float)whole[0];
- float floor_y = (float)whole[1];
- float ceil_x = floor_x + 1.0f;
- float ceil_y = floor_y + 1.0f;
- float height[3];
- float _x1, _y1, _z1, _x2, _y2, _z2, _x3, _y3, _z3;
- if(triangle == false){
- // 0
- // 1 2
- //FCNPC_GetZGround(floor_x, ceil_y, height[0]);
- height[0] = FindZ_For2DCoord(floor_x, ceil_y);
- //FCNPC_GetZGround(floor_x, floor_y, height[1]);
- height[1] = FindZ_For2DCoord(floor_x, floor_y);
- //FCNPC_GetZGround(ceil_x, floor_y, height[2]);
- height[2] = FindZ_For2DCoord(ceil_x, floor_y);
- _x1 = floor_x;
- _y1 = ceil_y;
- _z1 = height[0];
- _x2 = floor_x;
- _y2 = floor_y;
- _z2 = height[1];
- _x3 = ceil_x;
- _y3 = floor_y;
- _z3 = height[2];
- }else{
- // 0 1
- // 2
- //FCNPC_GetZGround(floor_x, ceil_y, height[0]);
- height[0] = FindZ_For2DCoord((float)floor_x, (float)ceil_y);
- //FCNPC_GetZGround(ceil_x, ceil_y, height[1]);
- height[1] = FindZ_For2DCoord((float)ceil_x, (float)ceil_y);
- //FCNPC_GetZGround(ceil_x, floor_y, height[2]);
- height[2] = FindZ_For2DCoord((float)ceil_x, (float)floor_y);
- _x1 = floor_x;
- _y1 = ceil_y;
- _z1 = height[0];
- _x2 = ceil_x;
- _y2 = ceil_y;
- _z2 = height[1];
- _x3 = ceil_x;
- _y3 = floor_y;
- _z3 = height[2];
- }
- //вершины полигона:
- //_x1=argument0 _y1=argument1 _z1=argument2
- //_x2=argument3 _y2=argument4 _z2=argument5
- //_x3=argument6 _y3=argument7 _z3=argument8
- //x и y точки, для которой нужно найти z:
- //Уравнение плоскости - A*x+B*y+C*z+D=0
- //где A, B, C - нормаль к поверхности.
- //у меня вместо переменных A, B и C будут nx, ny и nz
- //D - положение плосктости относительно начала координат.
- //Из этой формулы выражаем z,
- //получается: z=-(A*x+B*Y+D)/C
- //Вычисляем нормаль к плоскости полигона
- //и записываем координаты этого вектора в переменные nx, ny, nz.
- float nx = (_z1-_z2)*(_y3-_y2)-(_y1-_y2)*(_z3-_z2);
- float ny = (_x1-_x2)*(_z3-_z2)-(_z1-_z2)*(_x3-_x2);
- float nz = (_y1-_y2)*(_x3-_x2)-(_x1-_x2)*(_y3-_y2);
- float normlength = sqrt((nx * nx)+(ny * ny)+(nz * nz));
- nx /= normlength;
- ny /= normlength;
- nz /= normlength;
- float D = -(_x1*nx+_y1*ny+_z1*nz); //Находим положение плосктости относительно начала координат по этой формуле.
- return -(nx*x+ny*y+D)/nz; //вычисляем z по формуле
- }
- bool CMapAndreas::Unload()
- {
- // Close the file if neccessary
- if (mapFile != NULL)
- {
- fclose(mapFile);
- }
- // Free the used memory
- free(m_pPointData);
- //m_pPointData = NULL;
- m_iOperatingMode = MAP_ANDREAS_MODE_NONE;
- return true;
- }
- //----------------------------------------------------------
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement